     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.4
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.15 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 13/06/2022 (v0.2.1.4) ]
    13                                  ;	 04/02/2016 - Retro UNIX 386 v1.1 (Retro UNIX Kernel v0.2.1.0)	
    14                                  ;	 31/12/2021 - BugFix and Code Optimization (v0.2.1.1)
    15                                  ;	 03/03/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022
    16                                  ;	 04/04/2022 - Inode Table/List Address Modification (v0.2.1.2) -u5.s-
    17                                  ;	 22/04/2022 - BugFix ('mget' -u5.s-)
    18                                  ;	 29/04/2022 - BugFix ('syschmod' -u2.s-) (v0.2.1.2)
    19                                  ;	 ; (v0.2.1.3)
    20                                  ;	 09/05/2022 - u2.s (systat), u7.s (sysumount), diskinit.inc  
    21                                  ;	 15/05/2022 - u2.s (namei), u7.s (sysumount)
    22                                  ;	 01/06/2022 - BugFix ('set_date_time' -u0.s-) (v0.2.1.3)
    23                                  ;	 13/06/2022 - LPT1 (/dev/lpr) printing modification (v0.2.1.4)
    24                                  ;	 14/06/2022 - BugFix (video.inc,'set_cpos' <- u9.s 'putc' carry flg)
    25                                  ;
    26                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    27                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    28                                  ; <Bell Laboratories (17/3/1972)>
    29                                  ; <Preliminary Release of UNIX Implementation Document>
    30                                  ;
    31                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    32                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    33                                  ;
    34                                  ; ****************************************************************************
    35                                  ; 31/12/2021 - 15/05/2022
    36                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    37                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    38                                  
    39                                  ; 02/01/2022 - Code Optimization
    40                                  ; Runix Kernel v0.2.1.2
    41                                  ; 24/12/2021 - BugFix and Code Optimization
    42                                  ; Runix Kernel v0.2.1.1 
    43                                  
    44                                  ; 24/12/2013
    45                                  
    46                                  ; Entering protected mode:
    47                                  ; Derived from 'simple_asm.txt' source code file and 
    48                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    49                                  ; (gregor.brunmar@home.se)
    50                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    51                                  ;
    52                                  
    53                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    54                                  ; by Michael Chourdakis (2009) 
    55                                  ; http://www.codeproject.com/Articles/45788/
    56                                  ; http://www.michaelchourdakis.com
    57                                  ;
    58                                  
    59                                  ; Global Descriptor Table:
    60                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    61                                  ; by Linus Torvalds (1991-1992)
    62                                  ;
    63                                  
    64                                  KLOAD	equ 10000h ; Kernel loading address
    65                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    66                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    67                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    68                                  ; 19/03/2015
    69                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    70                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    71                                  ; 24/03/2015
    72                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    73                                  ; 19/03/2015
    74                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    75                                  		     ; (at the end of the 1st 4MB)
    76                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    77                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    78                                  
    79                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    80                                  ;; 27/12/2013
    81                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    82                                  
    83                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    84                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    85                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    86                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    87                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    88                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    89                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    90                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    91                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    92                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    93                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    94                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    95                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    96                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    97                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    98                                  ;----------------------------------------
    99                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
   100                                  ;-----------------------------------------------------------------------------
   101                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
   102                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
   103                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
   104                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
   105                                  
   106                                  ; Memory Allocation Table Address
   107                                  ; 05/11/2014
   108                                  ; 31/10/2014
   109                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   110                                  					; the 1st 1 MB memory space.
   111                                  					; (This address must be aligned
   112                                  					;  on 128 KB boundary, if it will be
   113                                  					;  changed later.)
   114                                  					; ((lower 17 bits of 32 bit M.A.T.
   115                                  					;   address must be ZERO)).
   116                                  					; ((((Reason: 32 bit allocation 
   117                                  					;     instructions, dword steps)))
   118                                  					; (((byte >> 12 --> page >> 5)))  
   119                                  ;04/11/2014	
   120                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   121                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   122                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   123                                  ;
   124                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   125                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   126                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   127                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   128                                  
   129                                  ; 17/02/2015 (unix386.s)
   130                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   131                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   132                                  ;
   133                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   134                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   135                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   136                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   137                                  
   138                                  
   139                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   140                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   141                                  ;
   142                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   143                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   144                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   145                                  		      ; otherwise it is standard FDPT with physical values 	
   146                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   147                                  		      ; (obsolete for IDE/ATA drives)
   148                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   149                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   150                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   151                                  			; Bit 4 : Reserved. Always 0
   152                                  			; Bit 3 : Set to 1 if more than 8 heads
   153                                  			; Bit 2-0 : Reserved. Alsways 0
   154                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   155                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   156                                  
   157                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   158                                  ; (11 bytes long) will be used by diskette handler/bios
   159                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   160                                  
   161                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   162                                  
   163                                  [ORG 0]
   164                                  
   165                                  KSTART: ; 01/01/2022
   166                                   
   167                                  	; 12/11/2014
   168                                  	; Save boot drive number (that is default root drive)
   169 00000000 8816[7A67]              	mov	[boot_drv], dl ; physical drv number
   170                                  
   171                                  	; Determine installed memory
   172                                  	; 31/10/2014
   173                                  	;
   174 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   175 00000007 CD15                    	int	15h	   ; for large configurations
   176 00000009 7308                    	jnc	short chk_ms
   177 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   178 0000000D CD15                    	int	15h
   179                                  	;	   
   180                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   181                                  	;out	70h, al ; select CMOS register
   182                                  	;in	al, 71h ; read data (1 byte)
   183                                  	;mov	cl, al
   184                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   185                                  	;out	70h, al ; select CMOS register
   186                                  	;in	al, 71h ; read data (1 byte)
   187                                  	;mov	ch, al
   188                                   	;      
   189 0000000F 89C1                    	mov	cx, ax
   190 00000011 31D2                    	xor	dx, dx
   191                                  chk_ms:
   192 00000013 890E[106A]              	mov	[mem_1m_1k], cx
   193 00000017 8916[146A]              	mov	[mem_16m_64k], dx
   194                                  	; 05/11/2014
   195                                  	;and	dx, dx
   196                                  	;jz	short L2
   197 0000001B 81F90004                        cmp     cx, 1024
   198 0000001F 7351                    	jnb	short L0
   199                                  		 ; insufficient memory_error	
   200                                  		 ; Minimum 2 MB memory is needed... 
   201                                  	; 05/11/2014
   202                                  	; (real mode error printing)
   203 00000021 FB                      	sti
   204 00000022 BE[3600]                	mov	si, msg_out_of_memory
   205 00000025 BB0700                  	mov	bx, 7
   206 00000028 B40E                    	mov	ah, 0Eh	; write tty
   207                                  oom_1:
   208 0000002A AC                      	lodsb
   209 0000002B 08C0                    	or	al, al
   210 0000002D 7404                    	jz	short oom_2
   211 0000002F CD10                    	int	10h
   212 00000031 EBF7                    	jmp	short oom_1
   213                                  oom_2:
   214 00000033 F4                              hlt
   215 00000034 EBFD                    	jmp	short oom_2
   216                                  
   217                                  ; 02/01/2022
   218                                  ; 05/11/2014
   219                                  msg_out_of_memory:
   220 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   221 00000039 496E73756666696369-             db      'Insufficient memory !'
   221 00000042 656E74206D656D6F72-
   221 0000004B 792021             
   222 0000004E 0D0A                    	db	0Dh, 0Ah
   223                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   224 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   224 00000059 324D42206D656D6F72-
   224 00000062 79206973206E656564-
   224 0000006B 65642E29           
   225 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   226                                  
   227                                  L0:
   228                                  %include 'diskinit.inc' ; 07/03/2015
   229                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - DISKINIT.INC
   230                              <1> ; Last Modification: 09/05/2022
   231                              <1> 
   232                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   233                              <1> 
   234                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   235                              <1> 
   236                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   237                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   238                              <1> ;L0:
   239                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   240                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   241 00000072 BA7F00              <1> 	mov	dx, 7Fh
   242                              <1> L1:	
   243 00000075 FEC2                <1> 	inc	dl
   244 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   245                              <1> 			; Phoenix EDD v1.1 - EDD v3
   246 00000079 BBAA55              <1> 	mov	bx, 55AAh
   247 0000007C CD13                <1> 	int 	13h
   248 0000007E 721A                <1> 	jc	short L2
   249                              <1> 
   250 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   251 00000084 7514                <1> 	jne	short L2
   252 00000086 FE06[7D67]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   253 0000008A 8816[7C67]          <1>         mov     [last_drv], dl  ; last hard disk number
   254 0000008E BB[0067]            <1> 	mov	bx, hd0_type - 80h
   255 00000091 01D3                <1> 	add	bx, dx	 
   256 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   257                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   258                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   259                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   260                              <1>                          ;            (EDD) ready (DPTE ready)
   261                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   262                              <1>                          ;            (EDD-3)
   263                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   264 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   265 00000098 72DB                <1> 	jb	short L1
   266                              <1> L2:
   267                              <1> 	; 23/11/2014
   268                              <1> 	; 19/11/2014
   269 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   270                              <1> 	; 04/02/2016 (esi -> si)
   271 0000009C BE[7E67]            <1> 	mov	si, fd0_type
   272                              <1> L3:
   273                              <1> 	; 14/01/2015
   274 0000009F 8816[7B67]          <1> 	mov	[drv], dl
   275                              <1> 	;
   276 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   277 000000A5 CD13                <1> 	int	13h	
   278 000000A7 7210                <1> 	jc	short L4
   279                              <1> 		; BL = drive type (for floppy drives)
   280                              <1> 		; DL = number of floppy drives
   281                              <1> 		;		
   282                              <1> 		; ES:DI = Address of DPT from BIOS
   283                              <1> 		;
   284 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   285                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   286                              <1> 	; 14/01/2015
   287 000000AB E8BB01              <1> 	call	set_disk_parms
   288                              <1> 	; 10/12/2014
   289 000000AE 81FE[7E67]          <1> 	cmp	si, fd0_type
   290 000000B2 7705                <1> 	ja	short L4
   291 000000B4 46                  <1> 	inc	si ; fd1_type
   292 000000B5 B201                <1> 	mov	dl, 1
   293 000000B7 EBE6                <1> 	jmp	short L3
   294                              <1> L4:
   295                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   296 000000B9 B27F                <1> 	mov	dl, 7Fh
   297                              <1> 	; 24/12/2014 (Temporary)
   298 000000BB 803E[7D67]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   299                              <1> 	;ja	L10       ; yes, all fixed disk operations
   300                              <1> 			  ; will be performed according to
   301                              <1> 			  ; present EDD specification
   302                              <1> 	; 02/01/2022
   303 000000C0 7603                <1> 	jna	short L5
   304 000000C2 E99100              <1> 	jmp	L10
   305                              <1> L5:
   306 000000C5 FEC2                <1> 	inc 	dl
   307 000000C7 8816[7B67]          <1>         mov     [drv], dl
   308 000000CB 8816[7C67]          <1>         mov     [last_drv], dl ; 14/01/2015
   309 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   310 000000D1 CD13                <1> 	int	13h	; (conventional function)
   311                              <1> 	;jc	L13	; fixed disk drive not ready
   312                              <1> 	; 02/01/2022
   313 000000D3 7303                <1> 	jnc	short L6
   314 000000D5 E98301              <1> 	jmp	L13
   315                              <1> L6:
   316 000000D8 8816[7D67]          <1>         mov     [hdc], dl ; number of drives
   317                              <1> 	;; 14/01/2013
   318                              <1> 	;;push	cx
   319 000000DC E88A01              <1> 	call	set_disk_parms
   320                              <1> 	;;pop	cx
   321                              <1> 	;
   322                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   323 000000DF 8A16[7B67]          <1>         mov     dl, [drv]
   324 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   325 000000E6 80FA80              <1> 	cmp	dl, 80h
   326 000000E9 7603                <1> 	jna	short L7
   327 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   328                              <1> L7:	
   329 000000EE 31C0                <1> 	xor	ax, ax
   330 000000F0 8ED8                <1> 	mov	ds, ax
   331 000000F2 8B37                <1>         mov     si, [bx]
   332 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   333 000000F7 8ED8                <1> 	mov	ds, ax
   334 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   335                              <1> 	;jne	L12 ; invalid FDPT
   336                              <1> 	; 02/01/2022
   337 000000FC 7403                <1> 	je	short L7_8
   338 000000FE E95601              <1> 	jmp	L12
   339                              <1> L7_8:
   340 00000101 BF0000              <1> 	mov	di, HD0_DPT
   341 00000104 80FA80              <1> 	cmp	dl, 80h
   342 00000107 7603                <1> 	jna	short L8
   343 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   344                              <1> L8:
   345                              <1> 	; 30/12/2014
   346 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   347 0000010F 8EC0                <1> 	mov	es, ax
   348                              <1> 	; 24/12/2014
   349 00000111 B90800              <1> 	mov	cx, 8
   350 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   351 00000116 8CC8                <1> 	mov	ax, cs
   352 00000118 8ED8                <1> 	mov	ds, ax
   353                              <1> 	; 02/02/2015
   354 0000011A 8A0E[7B67]          <1>         mov     cl, [drv]
   355 0000011E 88CB                <1> 	mov	bl, cl
   356 00000120 B8F001              <1> 	mov	ax, 1F0h
   357 00000123 80E301              <1> 	and	bl, 1
   358 00000126 7406                <1> 	jz	short L9
   359 00000128 C0E304              <1> 	shl	bl, 4
   360 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   361                              <1> L9:
   362 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   363 0000012F 050602              <1> 	add	ax, 206h
   364 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   365 00000133 88D8                <1> 	mov	al, bl
   366 00000135 04A0                <1> 	add	al, 0A0h
   367 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   368                              <1> 	;
   369 00000138 FE06[7B67]          <1> 	inc	byte [drv]
   370 0000013C BB[0067]            <1> 	mov	bx, hd0_type - 80h
   371 0000013F 01CB                <1> 	add	bx, cx
   372 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   373 00000144 A0[7D67]            <1> 	mov	al, [hdc]
   374 00000147 FEC8                <1> 	dec	al
   375                              <1> 	;jz	L13
   376                              <1> 	; 02/01/2022
   377 00000149 7408                <1> 	jz	short L9_10
   378 0000014B 80FA80              <1> 	cmp	dl, 80h
   379                              <1>         ;jna	L5
   380                              <1> 	;jmp	L13
   381                              <1> 	; 02/01/2022
   382 0000014E 7703                <1> 	ja	short L9_10
   383 00000150 E972FF              <1> 	jmp	L5
   384                              <1> L9_10:
   385 00000153 E90501              <1>         jmp     L13
   386                              <1> L10:
   387 00000156 FEC2                <1> 	inc 	dl
   388                              <1> 	; 25/12/2014
   389 00000158 8816[7B67]          <1> 	mov	[drv], dl
   390 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   391 0000015E CD13                <1> 	int	13h	; (conventional function)
   392                              <1> 	;jc	L13
   393                              <1> 	; 02/01/2022
   394 00000160 72F1                <1> 	jc	short L9_10
   395                              <1> 	; 14/01/2015
   396 00000162 8A16[7B67]          <1> 	mov	dl, [drv]
   397 00000166 52                  <1> 	push	dx
   398 00000167 51                  <1> 	push	cx
   399 00000168 E8FE00              <1> 	call	set_disk_parms
   400 0000016B 59                  <1> 	pop	cx
   401 0000016C 5A                  <1> 	pop	dx
   402                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   403                              <1> 	; 04/02/2016 (esi -> si)
   404                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   405                              <1> 	;		 ; at the '_end' of kernel.
   406                              <1> 	;mov	word [si], 30
   407                              <1> 	; 06/07/2016
   408 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   409                              <1> 	; 09/07/2016
   410 00000170 B81E00              <1> 	mov	ax, 001Eh
   411 00000173 8824                <1> 	mov	[si], ah ; 0
   412 00000175 46                  <1> 	inc	si
   413 00000176 8904                <1> 	mov	word [si], ax
   414                              <1>  	; word [si] = 30
   415                              <1> 	;
   416 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   417 0000017A CD13                <1> 	int	13h
   418                              <1>         ;jc	L13
   419                              <1> 	; 02/01/2022
   420 0000017C 72D5                <1> 	jc	short L9_10
   421                              <1> 	; 04/02/2016 (ebx -> bx)
   422                              <1> 	; 14/01/2015
   423                              <1> 	;sub	bx, bx
   424 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   425 00000180 88D3                <1> 	mov	bl, dl
   426 00000182 80EB80              <1> 	sub	bl, 80h
   427 00000185 81C3[8067]          <1> 	add	bx, hd0_type
   428 00000189 8A07                <1> 	mov 	al, [bx]
   429 0000018B 0C80                <1> 	or	al, 80h
   430 0000018D 8807                <1> 	mov 	[bx], al	
   431 0000018F 81EB[7E67]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   432 00000193 81C3[CA67]          <1> 	add	bx, drv.status
   433 00000197 8807                <1> 	mov	[bx], al
   434                              <1> 	; 04/02/2016 (eax -> ax)
   435 00000199 8B4410              <1> 	mov	ax, [si+16]
   436 0000019C 854412              <1> 	test	ax, [si+18]
   437 0000019F 7413                <1> 	jz	short L10_A0h 
   438                              <1> 			; 'CHS only' disks on EDD system 
   439                              <1> 			;  are reported with ZERO disk size
   440 000001A1 81EB[CA67]          <1> 	sub	bx, drv.status
   441 000001A5 C1E302              <1> 	shl	bx, 2
   442 000001A8 81C3[AE67]          <1> 	add	bx, drv.size ; disk size (in sectors)
   443 000001AC 8907                <1> 	mov	[bx], ax
   444 000001AE 8B4412              <1> 	mov	ax, [si+18]
   445                              <1> 	;mov	[bx], ax
   446                              <1> 	; 02/01/2022 (BugFix)
   447 000001B1 894702              <1> 	mov	[bx+2], ax
   448                              <1> 
   449                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   450                              <1> 	 ; for CHS disks (28/02/2015)
   451                              <1> 	; 30/12/2014
   452 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   453 000001B7 88D0                <1> 	mov	al, dl
   454 000001B9 83E003              <1> 	and 	ax, 3
   455 000001BC C0E005              <1> 	shl	al, 5 ; *32
   456 000001BF 01C7                <1> 	add 	di, ax
   457 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   458 000001C4 8EC0                <1> 	mov	es, ax
   459                              <1> 	;
   460 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   461 000001C8 88CC                <1> 	mov	ah, cl	
   462 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   463 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   464 000001CE AB                  <1> 	stosw		
   465 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   466 000001D1 FEC0                <1> 	inc	al
   467 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   468 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   469 000001D6 AA                  <1> 	stosb
   470 000001D7 8A440C              <1> 	mov	al, [si+12]
   471 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   472 000001DB 31C0                <1>  	xor	ax, ax
   473                              <1> 	;dec	ax	 ; 02/01/2015 
   474 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   475                              <1> 	;xor	al, al	 ; 02/01/2015	
   476 000001DE AA                  <1> 	stosb		 ; reserved
   477 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   478                              <1> 		         ; (do not disable retries, 
   479                              <1> 			 ; more than 8 heads)
   480 000001E1 AA                  <1> 	stosb
   481 000001E2 8B4404              <1> 	mov	ax, [si+4]
   482 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   483                              <1> 	;push	ax	 ; 02/01/2015
   484 000001E6 8A4408              <1> 	mov	al, [si+8]
   485 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   486 000001EA 29C0                <1> 	sub 	ax, ax
   487                              <1> 	;pop	ax	 ; 02/01/2015	
   488 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   489 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   490 000001EF 243F                <1> 	and 	al, 3Fh	
   491 000001F1 AA                  <1> 	stosb
   492                              <1> 	;sub	al, al	 ; checksum
   493                              <1> 	;stosb
   494                              <1> 	;
   495 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   496 000001F5 AD                  <1> 	lodsw
   497 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   498 000001F7 AD                  <1> 	lodsw
   499 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   500                              <1> 	;
   501                              <1> 	; checksum calculation
   502 000001F9 89FE                <1> 	mov	si, di
   503 000001FB 06                  <1> 	push	es
   504 000001FC 1F                  <1> 	pop	ds
   505                              <1> 	;mov	cx, 16
   506 000001FD B90F00              <1> 	mov 	cx, 15
   507 00000200 29CE                <1> 	sub	si, cx
   508 00000202 30E4                <1> 	xor	ah, ah
   509                              <1> 	;del	cl
   510                              <1> L11:		
   511 00000204 AC                  <1> 	lodsb
   512 00000205 00C4                <1> 	add	ah, al
   513 00000207 E2FB                <1> 	loop	L11
   514                              <1> 	;
   515 00000209 88E0                <1> 	mov	al, ah
   516 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   517 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   518                              <1> 	;
   519 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   520 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   521                              <1> 	;
   522                              <1> 	; 23/02/2015
   523 00000210 57                  <1> 	push	di
   524                              <1> 	; ES:DI points to DPTE (FDPTE) location
   525                              <1> 	;mov	cx, 8
   526 00000211 B108                <1> 	mov	cl, 8
   527 00000213 F3A5                <1> 	rep	movsw	
   528                              <1> 	;
   529                              <1> 	; 23/02/2015
   530                              <1> 	; (P)ATA drive and LBA validation
   531                              <1> 	; (invalidating SATA drives and setting
   532                              <1> 	; CHS type I/O for old type fixed disks)
   533 00000215 5B                  <1> 	pop	bx
   534 00000216 8CC8                <1> 	mov	ax, cs
   535 00000218 8ED8                <1> 	mov	ds, ax
   536 0000021A 268B07              <1> 	mov	ax, [es:bx]
   537 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   538 00000220 7418                <1> 	je	short L11a
   539 00000222 3D7001              <1> 	cmp	ax, 170h
   540 00000225 7413                <1> 	je	short L11a
   541                              <1> 	; invalidation 
   542                              <1> 	; (because base port address is not 1F0h or 170h)
   543 00000227 30FF                <1> 	xor	bh, bh
   544 00000229 88D3                <1> 	mov	bl, dl
   545 0000022B 80EB80              <1> 	sub	bl, 80h
   546 0000022E C687[8067]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   547 00000233 808F[CC67]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   548 00000238 EB14                <1> 	jmp	short L11b
   549                              <1> L11a:	
   550                              <1> 	; LBA validation
   551 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   552 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   553 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   554                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   555 00000242 28FF                <1> 	sub	bh, bh
   556 00000244 88D3                <1> 	mov	bl, dl
   557 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   558 00000249 80A7[CC67]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   559                              <1> 				; bit 0 = LBA ready bit
   560                              <1> 	; 'diskio' procedure will check this bit !
   561                              <1> L11b:
   562 0000024E 3A16[7C67]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   563 00000252 7307                <1>         jnb     short L13
   564 00000254 E9FFFE              <1>         jmp     L10
   565                              <1> L12:
   566                              <1> 	; Restore data registers
   567 00000257 8CC8                <1> 	mov	ax, cs
   568 00000259 8ED8                <1> 	mov	ds, ax	
   569                              <1> L13:
   570                              <1> 	; 13/12/2014
   571 0000025B 0E                  <1> 	push	cs
   572 0000025C 07                  <1> 	pop	es
   573                              <1> L14:
   574 0000025D B411                <1> 	mov 	ah, 11h
   575 0000025F CD16                <1> 	int 	16h
   576                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   577                              <1> 	; 02/01/2022
   578 00000261 7465                <1> 	jz	short L16
   579 00000263 B010                <1> 	mov	al, 10h
   580 00000265 CD16                <1> 	int 	16h
   581 00000267 EBF4                <1> 	jmp 	short L14
   582                              <1> L15:
   583                              <1> 
   584                              <1> ; //////
   585                              <1> 
   586                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   587                              <1> %if 0
   588                              <1> 	; 24/11/2014
   589                              <1> 	; 19/11/2014
   590                              <1> 	; 14/11/2014
   591                              <1> 	; Temporary code for disk searching code check
   592                              <1> 	;
   593                              <1> 	; This code will show existing (usable) drives and also
   594                              <1> 	; will show EDD interface support status for hard disks		
   595                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   596                              <1> 	; no need to get it again in protected mode...) 
   597                              <1> 	;	
   598                              <1> 	; 13/11/2014
   599                              <1> 	mov	bx, 7
   600                              <1> 	mov	ah, 0Eh
   601                              <1> 	mov	al, [fd0_type]
   602                              <1> 	and	al, al
   603                              <1> 	jz	short L15a
   604                              <1> 	mov	dl, al
   605                              <1> 	mov	al, 'F'
   606                              <1> 	int 	10h
   607                              <1> 	mov	al, 'D'
   608                              <1> 	int 	10h
   609                              <1> 	mov	al, '0'
   610                              <1> 	int 	10h
   611                              <1> 	mov	al, ' '
   612                              <1> 	int	10h
   613                              <1> 	call	L15c
   614                              <1> 	mov	al, ' '
   615                              <1> 	int	10h
   616                              <1> 	;
   617                              <1> 	mov	al, [fd1_type]
   618                              <1> 	and	al, al
   619                              <1> 	jz	short L15a
   620                              <1> 	mov	dl, al
   621                              <1> 	mov	al, 'F'
   622                              <1> 	int 	10h
   623                              <1> 	mov	al, 'D'
   624                              <1> 	int 	10h
   625                              <1> 	mov	al, '1'
   626                              <1> 	int 	10h
   627                              <1> 	mov	al, ' '
   628                              <1> 	int	10h
   629                              <1> 	call	L15c
   630                              <1> 	mov	al, ' '
   631                              <1> 	int	10h
   632                              <1> 	mov	al, ' '
   633                              <1> 	int	10h
   634                              <1> L15a:
   635                              <1> 	mov	al, [hd0_type]
   636                              <1> 	and	al, al
   637                              <1> 	jz	short L15b
   638                              <1> 	mov	dl, al
   639                              <1> 	mov	al, 'H'
   640                              <1> 	int 	10h
   641                              <1> 	mov	al, 'D'
   642                              <1> 	int 	10h
   643                              <1> 	mov	al, '0'
   644                              <1> 	int 	10h
   645                              <1> 	mov	al, ' '
   646                              <1> 	int 	10h
   647                              <1> 	call	L15c
   648                              <1> 	mov	al, ' '
   649                              <1> 	int	10h
   650                              <1> 	;
   651                              <1> 	mov	al, [hd1_type]
   652                              <1> 	and	al, al
   653                              <1> 	jz	short L15b
   654                              <1> 	mov	dl, al
   655                              <1> 	mov	al, 'H'
   656                              <1> 	int 	10h
   657                              <1> 	mov	al, 'D'
   658                              <1> 	int 	10h
   659                              <1> 	mov	al, '1'
   660                              <1> 	int 	10h
   661                              <1> 	mov	al, ' '
   662                              <1> 	int 	10h
   663                              <1> 	call	L15c
   664                              <1> 	mov	al, ' '
   665                              <1> 	int	10h
   666                              <1> 	;
   667                              <1> 	mov	al, [hd2_type]
   668                              <1> 	and	al, al
   669                              <1> 	jz	short L15b
   670                              <1> 	mov	dl, al
   671                              <1> 	mov	al, 'H'
   672                              <1> 	int 	10h
   673                              <1> 	mov	al, 'D'
   674                              <1> 	int 	10h
   675                              <1> 	mov	al, '2'
   676                              <1> 	int 	10h
   677                              <1> 	mov	al, ' '
   678                              <1> 	int 	10h
   679                              <1> 	call	L15c
   680                              <1> 	mov	al, ' '
   681                              <1> 	int	10h
   682                              <1> 	;
   683                              <1> 	mov	al, [hd3_type]
   684                              <1> 	and	al, al
   685                              <1> 	jz	short L15b
   686                              <1> 	mov	dl, al
   687                              <1> 	mov	al, 'H'
   688                              <1> 	int 	10h
   689                              <1> 	mov	al, 'D'
   690                              <1> 	int 	10h
   691                              <1> 	mov	al, '3'
   692                              <1> 	int 	10h
   693                              <1> 	mov	al, ' '
   694                              <1> 	int 	10h
   695                              <1> 	call	L15c
   696                              <1> 	mov	al, ' '
   697                              <1> 	int	10h
   698                              <1> 	;
   699                              <1> L15b:
   700                              <1> 	mov	al, 0Dh
   701                              <1> 	int 	10h	
   702                              <1> 	mov	al, 0Ah
   703                              <1> 	int 	10h
   704                              <1> 	;;xor	ah, ah
   705                              <1> 	;;int 	16h	
   706                              <1> 	;
   707                              <1>         ;jmp	L16  ; jmp short L16
   708                              <1>         ; 02/01/2022
   709                              <1> 	jmp	short L16
   710                              <1> 	;
   711                              <1> L15c:
   712                              <1> 	mov	dh, dl
   713                              <1> 	shr	dh, 4
   714                              <1> 	add	dh, 30h
   715                              <1> 	and	dl, 15
   716                              <1> 	add	dl, 30h
   717                              <1> 	mov	al, dh
   718                              <1> 	int	10h
   719                              <1> 	mov	al, dl
   720                              <1> 	int	10h
   721                              <1> 	retn
   722                              <1> 	;
   723                              <1> 	; end of temporary code for disk searching code check
   724                              <1> 
   725                              <1> %endif
   726                              <1> 
   727                              <1> ; //////
   728                              <1> 
   729                              <1> set_disk_parms:
   730                              <1> 	; 09/05/2022
   731                              <1> 	;	disksize = cylinders*spt*heads (*)
   732                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   733                              <1> 	;
   734                              <1> 	; 04/02/2016 (ebx -> bx)
   735                              <1> 	; 10/07/2015
   736                              <1> 	; 14/01/2015
   737                              <1> 	;push	bx
   738 00000269 28FF                <1> 	sub	bh, bh
   739 0000026B 8A1E[7B67]          <1> 	mov	bl, [drv]
   740 0000026F 80FB80              <1> 	cmp	bl, 80h
   741 00000272 7203                <1> 	jb	short sdp0
   742 00000274 80EB7E              <1> 	sub	bl, 7Eh
   743                              <1> sdp0:	
   744 00000277 81C3[CA67]          <1> 	add	bx, drv.status
   745 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   746                              <1> 	;
   747 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   748 00000280 88CC                <1> 	mov	ah, cl ; 
   749 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   750 00000285 81EB[CA67]          <1> 	sub	bx, drv.status
   751 00000289 D0E3                <1> 	shl	bl, 1
   752 0000028B 81C3[8467]          <1> 	add	bx, drv.cylinders
   753 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   754 00000290 8907                <1> 	mov	[bx], ax
   755 00000292 50                  <1> 	push	ax ; ** cylinders
   756 00000293 81EB[8467]          <1> 	sub	bx, drv.cylinders
   757 00000297 81C3[9267]          <1> 	add	bx, drv.heads
   758 0000029B 30E4                <1> 	xor	ah, ah
   759 0000029D 88F0                <1> 	mov	al, dh ; heads
   760 0000029F 40                  <1> 	inc	ax
   761 000002A0 8907                <1> 	mov	[bx], ax
   762 000002A2 81EB[9267]          <1>         sub     bx, drv.heads
   763 000002A6 81C3[A067]          <1>         add     bx, drv.spt
   764 000002AA 30ED                <1> 	xor	ch, ch
   765 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   766 000002AF 890F                <1> 	mov	[bx], cx
   767 000002B1 81EB[A067]          <1>         sub     bx, drv.spt
   768 000002B5 D1E3                <1> 	shl	bx, 1
   769 000002B7 81C3[AE67]          <1> 	add	bx, drv.size ; disk size (in sectors)
   770                              <1> 	; LBA size = cylinders * heads * secpertrack
   771 000002BB F7E1                <1> 	mul	cx 
   772 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   773 000002BF 58                  <1> 	pop	ax ; ** cylinders
   774                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   775                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   776 000002C0 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   777 000002C2 8907                <1> 	mov	[bx], ax
   778 000002C4 895702              <1> 	mov	[bx+2], dx
   779                              <1> 	;
   780                              <1> 	;pop	bx
   781 000002C7 C3                  <1> 	retn
   782                              <1> 
   783                              <1> ;align 2
   784                              <1> 
   785                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   786                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   787                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   788                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   789                              <1> 
   790                              <1> ;last_drv:
   791                              <1> ;	db  0
   792                              <1> ;drv_status:
   793                              <1> ;	db  0,0,0,0,0,0
   794                              <1> ;	db 0
   795                              <1> 
   796                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   797                              <1> 
   798                              <1> L16:
   229                                  
   230                                  	; 10/11/2014
   231 000002C8 FA                           	cli	; Disable interrupts (clear interrupt flag)
   232                                  		; Reset Interrupt MASK Registers (Master&Slave)
   233                                  	;mov	al, 0FFh	; mask off all interrupts
   234                                  	;out	21h, al		; on master PIC (8259)
   235                                  	;jmp 	$+2  ; (delay)
   236                                  	;out	0A1h, al	; on slave PIC (8259)
   237                                  	;
   238                                  	; Disable NMI 
   239 000002C9 B080                    	mov   	al, 80h 
   240 000002CB E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   241                                  	;23/02/2015
   242 000002CD 90                      	nop			;
   243                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   244                                  				; for preventing unknown state (!?)
   245                                  
   246                                  	; 02/01/2022
   247                                  	%define KERNELFSIZE KEND-KSTART 
   248                                  	;
   249                                   	; 20/08/2014
   250                                  	; Moving the kernel 64 KB back (to physical address 0)
   251                                  	; DS = CS = 1000h
   252                                  	; 05/11/2014
   253 000002CE 31C0                    	xor	ax, ax
   254 000002D0 8EC0                    	mov	es, ax ; ES = 0
   255                                  	;
   256                                  	;;mov	cx, (KEND - KLOAD)/4
   257                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   258 000002D2 B90C35                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   259 000002D5 31F6                    	xor	si, si
   260 000002D7 31FF                    	xor	di, di
   261                                  	;rep	movsd
   262 000002D9 F3A5                    	rep	movsw ; 02/01/2022
   263                                  	;
   264 000002DB 06                      	push	es ; 0
   265 000002DC 68[E002]                	push	L17
   266 000002DF CB                      	retf
   267                                  	;
   268                                  L17:
   269                                  	; Turn off the floppy drive motor
   270 000002E0 BAF203                          mov     dx, 3F2h
   271 000002E3 EE                              out     dx, al ; 0 ; 31/12/2013
   272                                  
   273                                  	; Enable access to memory above one megabyte
   274                                  L18:
   275 000002E4 E464                    	in	al, 64h
   276 000002E6 A802                    	test	al, 2
   277 000002E8 75FA                            jnz     short L18
   278 000002EA B0D1                    	mov	al, 0D1h	; Write output port
   279 000002EC E664                    	out	64h, al
   280                                  L19:
   281 000002EE E464                    	in	al, 64h
   282 000002F0 A802                    	test	al, 2
   283 000002F2 75FA                            jnz     short L19
   284 000002F4 B0DF                    	mov	al, 0DFh	; Enable A20 line
   285 000002F6 E660                    	out	60h, al
   286                                  ;L20:
   287                                  	;
   288                                  	; Load global descriptor table register
   289                                  
   290                                          ;mov     ax, cs
   291                                          ;mov     ds, ax
   292                                  
   293 000002F8 2E0F0116[A064]                  lgdt    [cs:gdtd]
   294                                  
   295 000002FE 0F20C0                          mov     eax, cr0
   296                                  	; or 	eax, 1
   297 00000301 40                      	inc     ax
   298 00000302 0F22C0                  	mov     cr0, eax
   299                                  
   300                                  	; Jump to 32 bit code
   301                                  	
   302 00000305 66                      	db 66h 			; Prefix for 32-bit
   303 00000306 EA                      	db 0EAh 		; Opcode for far jump
   304 00000307 [0D030000]              	dd StartPM 		; Offset to start, 32-bit
   305                                  				; (1000h:StartPM = StartPM + 10000h)
   306 0000030B 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   307                                  				; assuming that StartPM resides in code32
   308                                  
   309                                  [BITS 32] 
   310                                  
   311                                  StartPM:
   312                                  	; Kernel Base Address = 0 ; 30/12/2013
   313 0000030D 66B81000                	mov ax, KDATA           ; Save data segment identifier
   314 00000311 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   315 00000313 8EC0                           	mov es, ax              ; Move data segment into ES register
   316 00000315 8EE0                           	mov fs, ax              ; Move data segment into FS register
   317 00000317 8EE8                          	mov gs, ax              ; Move data segment into GS register
   318 00000319 8ED0                            mov ss, ax              ; Move data segment into SS register
   319 0000031B BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   320                                  
   321                                  clear_bss: ; Clear uninitialized data area
   322                                  	; 11/03/2015
   323 00000320 31C0                    	xor	eax, eax ; 0
   324                                  	;mov	ecx, (bss_end - bss_start)/4
   325                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   326                                  	; 02/01/2022
   327 00000322 B9BD050000              	mov	ecx, BSS_SIZE/4
   328 00000327 BF[206A0000]            	mov	edi, bss_start
   329 0000032C F3AB                    	rep	stosd  		
   330                                  
   331                                  memory_init:
   332                                  	; Initialize memory allocation table and page tables
   333                                  	;
   334                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   335                                  	; 16/11/2014
   336                                  	; 15/11/2014
   337                                  	; 07/11/2014
   338                                  	; 06/11/2014
   339                                  	; 05/11/2014
   340                                  	; 04/11/2014
   341                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   342                                  	;
   343                                  ;	xor	eax, eax
   344                                  ;	xor 	ecx, ecx
   345 0000032E B108                    	mov	cl, 8
   346 00000330 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   347 00000335 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   348                                  				   ; for the first 1 MB memory
   349                                  	;
   350 00000337 8B0D[106A0000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   351                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   352                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   353                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   354 0000033D C1E902                  	shr	ecx, 2	; 02/01/2022
   355 00000340 890D[906C0000]          	mov	[free_pages], ecx
   356 00000346 8B15[146A0000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   357                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   358                                  				   ; between 16 MB and 4 GB.
   359                                  	;or	dx, dx
   360 0000034C 09D2                    	or	edx, edx ; 02/01/2022
   361 0000034E 7412                    	jz	short mi_0
   362                                  	;
   363                                  	;mov	ax, dx
   364 00000350 89D0                    	mov	eax, edx ; 02/01/2022
   365 00000352 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   366 00000355 0105[906C0000]          	add	[free_pages], eax
   367 0000035B 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   368 00000360 EB06                    	jmp	short mi_1
   369                                  mi_0:
   370                                  	;mov	ax, cx
   371 00000362 89C8                    	mov	eax, ecx ; 02/01/2022	 
   372 00000364 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   373                                  mi_1:
   374 00000368 A3[8C6C0000]            	mov	[memory_size], eax ; Total available memory in pages
   375                                  				   ; 1 alloc. tbl. bit = 1 memory page
   376                                  				   ; 32 allocation bits = 32 mem. pages
   377                                  	;
   378 0000036D 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   379 00000372 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   380                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   381                                  				   ;  --> x M.A.T. pages, if y = 0
   382                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   383 00000375 A3[A06C0000]            	mov	[mat_size], eax ; 02/01/2022
   384 0000037A C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   385                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   386 0000037D 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   387                                  	; Set/Calculate Kernel's Page Directory Address
   388 0000037F 81C300001000            	add	ebx, MEM_ALLOC_TBL
   389 00000385 891D[886C0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   390                                  				   ; just after the last M.A.T. page
   391                                  	;
   392 0000038B 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   393 0000038E A3[986C0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   394                                  	;			   ; (allocation status search must be
   395                                  				   ; stopped after here)
   396 00000393 31C0                    	xor	eax, eax
   397 00000395 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   398                                  	;push	cx
   399 00000396 51                      	push	ecx ; 02/01/2022 
   400 00000397 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   401                                  				   ; count of 32 allocation bits
   402 0000039A F3AB                    	rep	stosd
   403                                  	;pop	cx
   404 0000039C 59                      	pop	ecx ; 02/01/2022
   405 0000039D 40                      	inc	eax		   ; 0
   406 0000039E 80E11F                  	and	cl, 31		   ; remain bits
   407 000003A1 7412                    	jz	short mi_4
   408 000003A3 8907                    	mov	[edi], eax	   ; reset
   409                                  mi_2:
   410 000003A5 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   411 000003A8 FEC9                    	dec	cl
   412 000003AA 7404                    	jz	short mi_3
   413 000003AC FEC0                    	inc	al
   414 000003AE EBF5                    	jmp	short mi_2
   415                                  mi_3:
   416 000003B0 28C0                    	sub	al, al	   	   ; 0
   417 000003B2 83C704                  	add	edi, 4		   ; 15/11/2014
   418                                  mi_4:
   419 000003B5 09D2                    	or	edx, edx ; 02/01/2022
   420                                  	;or	dx, dx		  ; check 16M to 4G memory space
   421 000003B7 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   422                                  	;	
   423 000003B9 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   424                                  	;	
   425 000003BE 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   426 000003C0 7405                    	jz	short mi_5	  ; jump if EDI points to 
   427                                  				  ;         end of first 16 MB	
   428                                  	;shr	ecx, 1		  ; convert to dword count
   429                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   430 000003C2 C1E902                  	shr	ecx, 2	; 02/01/2022
   431 000003C5 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   432                                  				  ; (memory hole under 16 MB)
   433                                  mi_5:
   434 000003C7 89D1                    	mov	ecx, edx ; 02/01/2022
   435                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   436 000003C9 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   437 000003CB 9C                      	pushf			  ; 16/11/2014		
   438 000003CC 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   439 000003CD F3AB                    	rep	stosd
   440 000003CF 40                      	inc	eax		  ; 0
   441 000003D0 9D                      	popf			  ; 16/11/2014
   442 000003D1 7305                    	jnc	short mi_6
   443 000003D3 6648                    	dec	ax		  ; eax = 0000FFFFh
   444 000003D5 AB                      	stosd
   445 000003D6 6640                    	inc	ax		  ; 0		
   446                                  mi_6:
   447 000003D8 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   448 000003DA 7309                    	jnb	short mi_7	  ; end of memory allocation table
   449                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   450 000003DC 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   451 000003DE 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   452                                  	;shr	ecx, 1		  ; to dword count
   453                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   454 000003E0 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   455 000003E3 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   456                                  mi_7:
   457                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   458 000003E5 BA00001000              	mov	edx, MEM_ALLOC_TBL
   459                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   460                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   461 000003EA 8B0D[A06C0000]          	mov	ecx, [mat_size] ; 02/01/2022
   462                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   463 000003F0 89D7                    	mov	edi, edx
   464 000003F2 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   465                                  				  ; byte offset in M.A.T.
   466                                  				  ; (1 M.A.T. byte points to 
   467                                  				  ;	      32768 bytes)
   468                                  				  ; Note: MEM_ALLOC_TBL address 
   469                                  				  ; must be aligned on 128 KB 
   470                                  				  ; boundary!
   471 000003F5 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   472                                  	; eax = 0
   473 000003F7 290D[906C0000]          	sub	[free_pages], ecx ; 07/11/2014
   474                                  mi_8:
   475 000003FD 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   476                                  	;dec	bl
   477 00000400 FEC9                    	dec	cl
   478 00000402 7404                    	jz	short mi_9
   479 00000404 FEC0                    	inc	al
   480 00000406 EBF5                    	jmp	short mi_8
   481                                  mi_9:
   482                                  	;
   483                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   484                                  	;		(allocate pages for system page tables)
   485                                  
   486                                  	; edx = MEM_ALLOC_TBL
   487 00000408 8B0D[8C6C0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   488 0000040E 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   489 00000414 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   490                                  				 ; page table count (PDE count)
   491                                  	;
   492 00000417 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   493                                  	;
   494 00000418 41                      	inc	ecx		 ; +1 for kernel page directory	
   495                                  	;
   496 00000419 290D[906C0000]          	sub	[free_pages], ecx ; 07/11/2014
   497                                  	;
   498 0000041F 8B35[886C0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   499 00000425 C1EE0C                  	shr	esi, 12		 ; convert to page number
   500                                  mi_10:
   501 00000428 89F0                    	mov	eax, esi	 ; allocation bit offset
   502 0000042A 89C3                    	mov	ebx, eax
   503 0000042C C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   504 0000042F 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   505                                  				 ;   to align on dword boundary
   506 00000432 83E01F                  	and	eax, 31		 ; set allocation bit position 
   507                                  				 ;  (bit 0 to bit 31)
   508                                  	;
   509 00000435 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   510                                  	;
   511 00000437 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   512                                  	;
   513 0000043A 46                      	inc	esi		 ; next page table
   514 0000043B E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   515                                  				 ; (ecx = page table count + 1)
   516                                  	;
   517 0000043D 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   518                                  	;
   519                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   520                                  	;
   521                                  	; Initialize Kernel's Page Directory
   522 0000043E 8B3D[886C0000]          	mov	edi, [k_page_dir]
   523 00000444 89F8                    	mov	eax, edi
   524 00000446 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   525                                  		     	      ; supervisor + read&write + present
   526 00000448 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   527                                  mi_11:
   528 0000044A 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   529                                  			        ; EAX points to next page table
   530 0000044F AB                      	stosd
   531 00000450 E2F8                    	loop	mi_11
   532 00000452 29C0                    	sub	eax, eax	; Empty PDE
   533                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   534                                  	; 02/01/2022
   535 00000454 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   536 00000456 29D1                    	sub	ecx, edx
   537 00000458 7402                    	jz	short mi_12
   538 0000045A F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   539                                  	;
   540                                  	; Initialization of Kernel's Page Directory is OK, here.
   541                                  mi_12:
   542                                  	; Initialize Kernel's Page Tables
   543                                  	;
   544                                  	; (EDI points to address of page table 0)
   545                                  	; eax = 0
   546 0000045C 8B0D[8C6C0000]          	mov	ecx, [memory_size] ; memory size in pages
   547 00000462 89CA                    	mov	edx, ecx	; (***)
   548 00000464 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   549                                  			     ; supervisor + read&write + present
   550                                  mi_13:
   551 00000466 AB                      	stosd
   552 00000467 0500100000              	add	eax, 4096	
   553 0000046C E2F8                    	loop	mi_13
   554                                  	; 02/01/2022
   555 0000046E 66B9FF03                	mov	cx, 1023
   556 00000472 21CA                    	and	edx, ecx
   557                                  	;and	dx, 1023	; (***)
   558 00000474 7407                    	jz	short mi_14
   559                                  	;mov	cx, 1024	
   560                                  	; 02/01/2022
   561                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   562 00000476 41                      	inc	ecx ; ecx = 1024
   563 00000477 29D1                    	sub	ecx, edx
   564                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   565 00000479 31C0                    	xor	eax, eax
   566 0000047B F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   567                                  				; of the last page table
   568                                  mi_14:
   569                                  	;  Initialization of Kernel's Page Tables is OK, here.
   570                                  	;
   571 0000047D 89F8                    	mov	eax, edi	; end of the last page table page
   572                                  			        ; (beginging of user space pages)
   573 0000047F C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   574 00000482 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   575                                  				; aligning on dword boundary
   576                                  	 
   577 00000484 A3[9C6C0000]            	mov	[first_page], eax
   578 00000489 A3[946C0000]            	mov	[next_page], eax ; The first free page pointer
   579                                  				 ; for user programs
   580                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   581                                  	;
   582                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   583                                  	;
   584                                  	
   585                                  	; Enable paging
   586                                  	;
   587 0000048E A1[886C0000]                    mov     eax, [k_page_dir]
   588 00000493 0F22D8                  	mov	cr3, eax
   589 00000496 0F20C0                  	mov	eax, cr0
   590 00000499 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   591 0000049E 0F22C0                  	mov	cr0, eax
   592                                          ;jmp    KCODE:StartPMP
   593                                  
   594 000004A1 EA                      	db 0EAh 		; Opcode for far jump
   595 000004A2 [A8040000]                      dd StartPMP		; 32 bit offset
   596 000004A6 0800                    	dw KCODE		; kernel code segment descriptor
   597                                  
   598                                  StartPMP:
   599                                  	; 06/11//2014
   600                                  	; Clear video page 0
   601                                  	;
   602                                  	; Temporary Code
   603                                  	;
   604                                  	;mov	ecx, 80*25/2
   605 000004A8 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   606 000004AC BF00800B00              	mov	edi, 0B8000h
   607 000004B1 57                      	push	edi ; * ; 02/01/2022
   608 000004B2 31C0                    	xor	eax, eax	; black background, black fore color
   609 000004B4 F3AB                    	rep	stosd
   610                                  	
   611                                  	; 19/08/2014
   612                                  	; Kernel Base Address = 0
   613                                  	; It is mapped to (physically) 0 in the page table.
   614                                  	; So, here is exactly 'StartPMP' address.
   615                                  	;
   616                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   617                                  	;;mov	esi, msgPM
   618                                  	;; 14/08/2015 (kernel version message will appear
   619                                  	;;	       when protected mode and paging is enabled)
   620 000004B6 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   621 000004B8 BE[E0670000]            	mov	esi, msgKVER
   622 000004BD 5F                      	pop	edi ; * ; 02/01/2022
   623                                  	;mov	edi, 0B8000h ; 27/08/2014
   624                                  	; 20/08/2014
   625 000004BE E892010000              	call	printk
   626                                  
   627                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   628                                  	; // Set IRQ offsets
   629                                  	;
   630                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   631                                  	;
   632                                  					;; ICW1
   633 000004C3 B011                    	mov	al, 11h			; Initialization sequence
   634 000004C5 E620                    	out	20h, al			; 	8259A-1
   635                                  	; jmp 	$+2
   636 000004C7 E6A0                    	out	0A0h, al		; 	8259A-2
   637                                  					;; ICW2
   638 000004C9 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   639 000004CB E621                    	out	21h, al			;	for 8259A-1
   640                                  	; jmp 	$+2
   641 000004CD B028                    	mov	al, 28h			; Start of hardware ints (28h)
   642 000004CF E6A1                    	out	0A1h, al		; 	for 8259A-2
   643                                  					;
   644 000004D1 B004                    	mov	al, 04h			;; ICW3
   645 000004D3 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   646                                  	; jmp 	$+2
   647 000004D5 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   648 000004D7 E6A1                    	out	0A1h, al		;
   649                                  					;; ICW4
   650 000004D9 B001                    	mov	al, 01h	 		;
   651 000004DB E621                    	out	21h, al			; 	8086 mode, normal EOI	
   652                                  	; jmp 	$+2
   653 000004DD E6A1                    	out	0A1h, al		;	for both chips.
   654                                  
   655                                  	;mov	al, 0FFh	; mask off all interrupts for now
   656                                  	;out	21h, al
   657                                  	;; jmp 	$+2
   658                                  	;out	0A1h, al
   659                                  
   660                                  	; 02/04/2015
   661                                  	; 26/03/2015 System call (INT 30h) modification
   662                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   663                                  	;
   664                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   665                                  	;  setup_idt:
   666                                  	;
   667                                          ;; 16/02/2015
   668                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   669                                  	; 21/08/2014 (timer_int)
   670 000004DF BE[AC640000]            	mov	esi, ilist
   671 000004E4 8D3D[206A0000]          	lea	edi, [idt]
   672                                  	; 26/03/2015
   673 000004EA B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   674                                  	; 02/04/2015
   675 000004EF BB00000800              	mov	ebx,  80000h
   676                                  rp_sidt1:
   677 000004F4 AD                      	lodsd
   678 000004F5 89C2                    	mov	edx, eax
   679 000004F7 66BA008E                	mov	dx, 8E00h
   680 000004FB 6689C3                  	mov	bx, ax
   681 000004FE 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   682                                         			        ; /* interrupt gate - dpl=0, present */
   683 00000500 AB                      	stosd	; selector & offset bits 0-15 	
   684 00000501 89D0                    	mov	eax, edx
   685 00000503 AB                      	stosd	; attributes & offset bits 16-23
   686 00000504 E2EE                    	loop	rp_sidt1
   687 00000506 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   688                                  rp_sidt2:
   689 00000508 AD                      	lodsd
   690 00000509 21C0                    	and	eax, eax
   691 0000050B 7413                    	jz	short rp_sidt3
   692 0000050D 89C2                    	mov	edx, eax
   693 0000050F 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   694 00000513 6689C3                  	mov	bx, ax
   695 00000516 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   696 00000518 AB                      	stosd
   697 00000519 89D0                    	mov	eax, edx
   698 0000051B AB                      	stosd
   699 0000051C E2EA                    	loop	rp_sidt2
   700 0000051E EB16                    	jmp	short sidt_OK
   701                                  rp_sidt3:
   702 00000520 B8[79090000]            	mov	eax, ignore_int
   703 00000525 89C2                    	mov	edx, eax
   704 00000527 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   705 0000052B 6689C3                  	mov	bx, ax
   706 0000052E 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   707                                  rp_sidt4:
   708 00000530 AB                      	stosd
   709 00000531 92                      	xchg	eax, edx
   710 00000532 AB                      	stosd
   711 00000533 92                      	xchg	edx, eax
   712 00000534 E2FA                    	loop	rp_sidt4
   713                                  sidt_OK: 
   714 00000536 0F011D[A6640000]        	lidt 	[idtd]
   715                                  	;
   716                                  	; TSS descriptor setup ; 24/03/2015
   717 0000053D B8[206C0000]            	mov	eax, task_state_segment
   718 00000542 66A3[9A640000]          	mov	[gdt_tss0], ax
   719 00000548 C1C010                  	rol	eax, 16
   720 0000054B A2[9C640000]            	mov	[gdt_tss1], al
   721 00000550 8825[9F640000]          	mov	[gdt_tss2], ah
   722 00000556 66C705[866C0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   722 0000055E 00                 
   723                                  		; 
   724                                  		; IO Map Base address (When this address points
   725                                  		; to end of the TSS, CPU does not use IO port 
   726                                  		; permission bit map for RING 3 IO permissions, 
   727                                  		; access to any IO ports in ring 3 will be forbidden.)
   728                                   		;
   729                                  	;mov	[tss.esp0], esp ; TSS offset 4
   730                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   731 0000055F 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   732                                  			 ; occurs (or a system call -software INT- is requested)
   733                                  			 ; while cpu running in ring 3 (in user mode).				
   734                                  			 ; (Kernel stack pointer and segment will be loaded
   735                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   736 00000563 0F00D8                  	ltr	ax  ; Load task register
   737                                  	;
   738                                  esp0_set0:
   739                                  	; 30/07/2015
   740 00000566 8B0D[8C6C0000]          	mov 	ecx, [memory_size] ; memory size in pages
   741 0000056C C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   742 0000056F 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   743                                  			  ; (kernel mode virtual address)
   744 00000575 7605                    	jna	short esp0_set1
   745                                  	;
   746                                  	; If available memory > CORE (end of the 1st 4 MB)
   747                                  	; set stack pointer to CORE
   748                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   749                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   750 00000577 B900004000              	mov	ecx, CORE
   751                                  esp0_set1:
   752 0000057C 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   753                                  esp0_set_ok:
   754                                  	; 30/07/2015 (**tss.esp0**) 
   755 0000057E 8925[246C0000]          	mov	[tss.esp0], esp
   756 00000584 66C705[286C0000]10-             mov     word [tss.ss0], KDATA
   756 0000058C 00                 
   757                                  	; 14/08/2015
   758                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   759                                  	;
   760                                  	;cli	; Disable interrupts (for CPU)
   761                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   762                                  	;
   763 0000058D 30C0                    	xor	al, al		; Enable all hardware interrupts!
   764 0000058F E621                    	out	21h, al		; (IBM PC-AT compatibility)
   765 00000591 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   766 00000593 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   767                                  				; (Even if related hardware component
   768                                  				;  does not exist!)
   769                                  	; Enable NMI 
   770 00000595 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   771 00000597 E670                    	out  	70h, al
   772                                  	; 23/02/2015
   773 00000599 90                      	nop
   774 0000059A E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   775                                  				; for preventing unknown state (!?)
   776                                  	;
   777                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   778                                  	;
   779                                  	; 02/09/2014
   780                                  	;xor	bx, bx
   781                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   782                                  	; 27/02/2022	
   783 0000059C 31DB                    	xor	ebx, ebx
   784 0000059E 31D2                    	xor	edx, edx
   785 000005A0 B602                    	mov	dh, 2
   786 000005A2 E8240F0000              	call	set_cpos
   787                                  	;
   788                                  	; 06/11/2014
   789                                  	; Temporary Code
   790                                  	;
   791 000005A7 E899100000              	call	memory_info
   792                                  	; 14/08/2015
   793                                  	;call getch ; 28/02/2015
   794                                  drv_init:
   795 000005AC FB                      	sti	; Enable Interrupts 
   796                                  	; 06/02/2015
   797 000005AD 8B15[80670000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   798 000005B3 668B1D[7E670000]        	mov	bx, [fd0_type] ; fd0, fd1
   799                                  	; 22/02/2015
   800 000005BA 6621DB                  	and	bx, bx
   801 000005BD 751B                    	jnz	short di1
   802                                  	;
   803 000005BF 09D2                    	or 	edx, edx
   804 000005C1 7529                    	jnz	short di2
   805                                  	;
   806                                  setup_error:
   807 000005C3 BE[C9680000]            	mov 	esi, setup_error_msg
   808                                  psem:	
   809 000005C8 AC                      	lodsb
   810 000005C9 08C0                    	or	al, al
   811                                  	;jz	short haltx ; 22/02/2015
   812 000005CB 7426                    	jz	short di3
   813 000005CD 56                      	push	esi
   814 000005CE 31DB                    	xor	ebx, ebx ; 0
   815                                  			; Video page 0 (bl=0)
   816 000005D0 B407                    	mov	ah, 07h ; Black background, 
   817                                  			; light gray forecolor
   818 000005D2 E8EA0D0000              	call	write_tty
   819 000005D7 5E                      	pop	esi
   820 000005D8 EBEE                    	jmp	short psem
   821                                  
   822                                  di1:
   823                                  	; supress 'jmp short T6'
   824                                  	;  (activate fdc motor control code)
   825 000005DA 66C705[D6060000]90-     	mov	word [T5], 9090h ; nop
   825 000005E2 90                 
   826                                  	;
   827                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   828                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   829                                  	;stosw
   830                                  	;mov 	ax, cs
   831                                  	;stosw
   832                                  	;; 16/02/2015
   833                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   834                                  	;
   835 000005E3 E86E1F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   836                                  	;
   837 000005E8 09D2                    	or	edx, edx
   838 000005EA 7407                            jz      short di3
   839                                  di2:
   840 000005EC E8AB1F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   841 000005F1 72D0                            jc      short setup_error
   842                                  di3:
   843 000005F3 E821100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   844                                  	;
   845 000005F8 E8CC5D0000              	call	display_disks ; 07/03/2015  (Temporary)
   846                                  ;haltx:
   847                                  	; 14/08/2015
   848                                  	;call	getch ; 22/02/2015
   849 000005FD FB                      	sti	; Enable interrupts (for CPU)
   850                                  	; 14/08/2015
   851                                  	;mov 	ecx, 0FFFFFFFh
   852                                  	; 24/12/2021
   853 000005FE B9FFFF2F00              	mov 	ecx, 02FFFFFh
   854                                  md_info_msg_wait:
   855 00000603 51                      	push 	ecx
   856 00000604 B001                    	mov	al, 1
   857 00000606 8A25[B66C0000]          	mov 	ah, [ptty] ; active (current) video page
   858 0000060C E8A35A0000              	call	getc_n
   859 00000611 59                      	pop	ecx
   860 00000612 7502                    	jnz	short md_info_msg_ok
   861 00000614 E2ED                    	loop	md_info_msg_wait
   862                                  md_info_msg_ok:
   863                                  	; 30/06/2015
   864 00000616 E88C2C0000              	call	sys_init
   865                                  	;
   866                                  	;jmp 	cpu_reset ; 22/02/2015
   867                                  hang:
   868                                  	; 24/12/2021
   869 0000061B 29C0                    	sub	eax, eax
   870                                  _hang:	
   871                                  	; 23/02/2015
   872                                  	;sti			; Enable interrupts
   873 0000061D F4                      	hlt
   874                                  	;
   875                                  	;nop
   876                                  	;; 03/12/2014
   877                                  	;; 28/08/2014
   878                                  	;mov	ah, 11h
   879                                  	;call	getc
   880                                  	;jz      _c8
   881                                  	;
   882                                  	; 23/02/2015
   883                                  	; 06/02/2015
   884                                  	; 07/09/2014
   885 0000061E 31DB                    	xor	ebx, ebx
   886 00000620 8A1D[B66C0000]          	mov	bl, [ptty]	; active_page
   887 00000626 89DE                    	mov	esi, ebx
   888 00000628 66D1E6                  	shl 	si, 1
   889 0000062B 81C6[B86C0000]          	add	esi, ttychr
   890 00000631 668B06                  	mov	ax, [esi]
   891                                  	;and	ax, ax
   892                                  	;;jz	short _c8
   893                                  	;jz	short hang
   894                                  	; 24/12/2021
   895 00000634 21C0                    	and	eax, eax
   896 00000636 74E5                    	jz	short _hang
   897 00000638 66C7060000              	mov	word [esi], 0
   898 0000063D 80FB03                  	cmp	bl, 3		; Video page 3
   899                                  	;jb	short _c8
   900 00000640 72D9                    	jb	short hang
   901                                  	;	
   902                                  	; 02/09/2014
   903 00000642 B40E                    	mov	ah, 0Eh		; Yellow character 
   904                                  				; on black background
   905                                  	; 24/12/2021 (32 bit reg push-pop)
   906                                  	; 07/09/2014
   907                                  nxtl:
   908 00000644 53                      	push	ebx
   909                                  	;
   910                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   911                                  				; bh = 0 (video mode)
   912                                  				; Retro UNIX 386 v1 - Video Mode 0
   913                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   914 00000645 50                      	push	eax
   915 00000646 E8760D0000              	call 	write_tty
   916 0000064B 58                      	pop	eax
   917                                  	;pop	bx
   918 0000064C 5B                      	pop	ebx
   919 0000064D 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   920                                  	;jne	short _c8
   921 0000064F 75CA                    	jne	short hang
   922 00000651 B00A                    	mov	al, 0Ah		; next line
   923 00000653 EBEF                    	jmp	short nxtl
   924                                  	
   925                                  ;_c8:
   926                                  ;	; 25/08/2014
   927                                  ;	cli			; Disable interrupts
   928                                  ;	mov	al, [scounter + 1]
   929                                  ;	and	al, al
   930                                  ;	jnz	hang
   931                                  ;	call	rtc_p
   932                                  ;	jmp     hang
   933                                  
   934                                  
   935                                  	; 27/08/2014
   936                                  	; 20/08/2014
   937                                  printk:
   938                                          ;mov    edi, [scr_row]
   939                                  pkl:
   940 00000655 AC                      	lodsb
   941 00000656 08C0                    	or 	al, al
   942 00000658 7404                    	jz	short pkr
   943 0000065A 66AB                    	stosw
   944 0000065C EBF7                    	jmp	short pkl
   945                                  pkr:
   946 0000065E C3                      	retn
   947                                  
   948                                  ; 25/07/2015
   949                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   950                                  ; 17/02/2015
   951                                  ; 06/02/2015 (unix386.s)
   952                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   953                                  ;
   954                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   955                                  ;
   956                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   957                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   958                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   959                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   960                                  ;									       :
   961                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   962                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   963                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   964                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   965                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   966                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   967                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   968                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   969                                  ;-------------------------------------------------------------------------------
   970                                  ;
   971                                  
   972                                  timer_int:	; IRQ 0
   973                                  ;int_08h:	; Timer
   974                                  	; 14/10/2015
   975                                  	; Here, we are simulating system call entry (for task switch)
   976                                  	; (If multitasking is enabled, 
   977                                  	; 'clock' procedure may jump to 'sysrelease')
   978 0000065F 1E                      	push	ds
   979 00000660 06                      	push	es
   980 00000661 0FA0                    	push	fs
   981 00000663 0FA8                    	push	gs
   982 00000665 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   983 00000666 66B91000                	mov     cx, KDATA
   984 0000066A 8ED9                            mov     ds, cx
   985 0000066C 8EC1                            mov     es, cx
   986 0000066E 8EE1                            mov     fs, cx
   987 00000670 8EE9                            mov     gs, cx
   988                                  	;
   989 00000672 0F20D9                  	mov	ecx, cr3
   990 00000675 890D[18070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   991                                  	;
   992 0000067B 3B0D[886C0000]          	cmp 	ecx, [k_page_dir]
   993 00000681 741F                    	je	short T3
   994                                  	;
   995                                  	; timer interrupt has been occurred while OS is in user mode
   996 00000683 A3[4C700000]            	mov 	[u.r0], eax
   997 00000688 89E1                    	mov	ecx, esp
   998 0000068A 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   999 0000068D 890D[44700000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
  1000 00000693 8925[48700000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
  1001                                  	;
  1002 00000699 8B0D[886C0000]          	mov	ecx, [k_page_dir]
  1003 0000069F 0F22D9                  	mov	cr3, ecx
  1004                                  T3:
  1005 000006A2 FB                      	sti				; INTERRUPTS BACK ON
  1006 000006A3 66FF05[046D0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
  1007 000006AA 7507                    	JNZ	short T4		; GO TO TEST_DAY
  1008 000006AC 66FF05[066D0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
  1009                                  T4:					; TEST_DAY
  1010 000006B3 66833D[066D0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
  1011 000006BB 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1012 000006BD 66813D[046D0000]B0-     	CMP	word [TIMER_LOW],0B0H
  1012 000006C5 00                 
  1013 000006C6 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1014                                  
  1015                                  ;-----	TIMER HAS GONE 24 HOURS
  1016                                  	;;SUB	AX,AX
  1017                                  	;MOV	[TIMER_HIGH],AX
  1018                                  	;MOV	[TIMER_LOW],AX
  1019 000006C8 29C0                    	sub	eax, eax
  1020 000006CA A3[046D0000]            	mov	[TIMER_LH], eax
  1021                                  	;	
  1022 000006CF C605[086D0000]01        	MOV	byte [TIMER_OFL],1
  1023                                  
  1024                                  ;-----	TEST FOR DISKETTE TIME OUT
  1025                                  
  1026                                  T5:
  1027                                  	; 23/12/2014
  1028 000006D6 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1029                                  					; (9090h) if a floppy disk
  1030                                  					; is detected.
  1031                                  	;mov	al,[CS:MOTOR_COUNT]
  1032 000006D8 A0[0B6D0000]            	mov	al, [MOTOR_COUNT]
  1033 000006DD FEC8                    	dec	al
  1034                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1035 000006DF A2[0B6D0000]            	mov	[MOTOR_COUNT], al
  1036                                  	;mov	[ORG_MOTOR_COUNT], al
  1037 000006E4 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1038 000006E6 B0F0                    	mov 	al,0F0h
  1039                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1040 000006E8 2005[0A6D0000]          	and	[MOTOR_STATUS], al
  1041                                  	;and	[ORG_MOTOR_STATUS], al
  1042 000006EE B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1043                                  					; bit 2 = enable controller
  1044                                  					;	1 = normal operation
  1045                                  					;	0 = reset	
  1046                                  					; bit 0, 1 = drive select
  1047                                  					; bit 4-7 = motor running bits 
  1048 000006F0 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1049 000006F4 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1050                                  T6:	
  1051                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1052                                  					; TIMER TICK INTERRUPT
  1053                                  	;;inc	word [wait_count] ;;27/02/2015
  1054                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1055                                  	;;;;cli
  1056                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1057 000006F5 FF15[10070000]          	call	[x_timer] ; 14/05/2015
  1058                                  T7:
  1059                                  	; 14/10/2015
  1060 000006FB B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1061 000006FD FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1062 000006FE E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1063                                  	;
  1064 00000700 A1[18070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1065 00000705 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1066                                  	;
  1067 00000708 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1068                                  	;
  1069 00000709 0FA9                    	pop	gs
  1070 0000070B 0FA1                    	pop	fs
  1071 0000070D 07                      	pop	es
  1072 0000070E 1F                      	pop	ds
  1073 0000070F CF                      	iretd	; return from interrupt
  1074                                  
  1075                                  
  1076                                  ; ////////////////
  1077                                  
  1078                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1079                                  x_timer:
  1080 00000710 [1C070000]              	dd 	u_timer			; 14/05/2015
  1081                                  	;dd	clock
  1082                                  
  1083                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1084                                  x_rtci:
  1085 00000714 [520A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1086                                  
  1087                                  ; 14/10/2015
  1088 00000718 00000000                cr3reg: dd 0
  1089                                  
  1090                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1091                                  	; 06/02/2015
  1092                                  	; 07/09/2014
  1093                                  	; 21/08/2014
  1094                                  u_timer:
  1095                                  ;timer_int:	; IRQ 0
  1096                                  	; 06/02/2015
  1097                                  	;push	eax
  1098                                  	;push	edx
  1099                                  	;push	ecx
  1100                                  	;push	ebx
  1101                                  	;push	ds
  1102                                  	;push	es
  1103                                  	;mov	eax, KDATA
  1104                                  	;mov	ds, ax
  1105                                  	;mov	es, ax
  1106 0000071C FF05[CC6C0000]          	inc	dword [tcount]
  1107 00000722 BB[52680000]            	mov	ebx, tcountstr + 4
  1108                                  	;mov	ax, [tcount]
  1109                                  	; 24/12/2021
  1110 00000727 A1[CC6C0000]            	mov	eax, [tcount]
  1111 0000072C B90A000000              	mov	ecx, 10
  1112                                  rp_divtcnt:
  1113 00000731 31D2                    	xor	edx, edx
  1114 00000733 F7F1                    	div	ecx
  1115 00000735 80C230                  	add	dl, 30h
  1116 00000738 8813                    	mov	[ebx], dl
  1117                                  	;or	ax, ax
  1118                                  	; 24/12/2021
  1119 0000073A 09C0                    	or	eax, eax
  1120 0000073C 7403                    	jz	short print_lzero
  1121 0000073E 4B                      	dec	ebx
  1122 0000073F EBF0                    	jmp	short rp_divtcnt
  1123                                  print_lzero:
  1124 00000741 81FB[4E680000]          	cmp	ebx, tcountstr
  1125 00000747 7606                    	jna	short print_tcount
  1126 00000749 4B                      	dec	ebx
  1127 0000074A C60330                   	mov	byte [ebx], 30h
  1128 0000074D EBF2                    	jmp	short print_lzero
  1129                                  print_tcount:
  1130 0000074F 56                      	push	esi
  1131 00000750 57                      	push	edi
  1132 00000751 BE[2A680000]            	mov	esi, timer_msg ; Timer interrupt message
  1133                                  	; 07/09/2014
  1134                                  	;mov	bx, 1	; Video page 1
  1135                                  	; 24/12/2021
  1136 00000756 29DB                    	sub	ebx, ebx
  1137                                  	;inc	bl ; ebx = 1
  1138                                  	; 02/01/2022
  1139 00000758 B306                    	mov	bl, 6	; Video page 6
  1140                                  ptmsg:
  1141 0000075A AC                      	lodsb
  1142 0000075B 08C0                    	or	al, al
  1143 0000075D 740D                    	jz	short ptmsg_ok
  1144 0000075F 56                      	push	esi
  1145                                  	;push	bx
  1146                                  	; 24/12/2021
  1147 00000760 53                              push	ebx
  1148 00000761 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1149 00000763 E8590C0000              	call 	write_tty
  1150                                  	;pop	bx
  1151                                  	; 24/12/2021
  1152 00000768 5B                      	pop	ebx
  1153 00000769 5E                      	pop	esi
  1154 0000076A EBEE                    	jmp	short ptmsg
  1155                                  	;; 27/08/2014
  1156                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1157                                  	;call	printk
  1158                                  	;
  1159                                  ptmsg_ok:
  1160                                  	; 07/09/2014
  1161                                  	;xor	dx, dx		; column 0, row 0
  1162                                  	; 24/12/2021
  1163 0000076C 31D2                    	xor	edx, edx
  1164 0000076E E8580D0000              	call	set_cpos	; set cursor position to 0,0 
  1165                                  	; 23/02/2015
  1166                                  	; 25/08/2014
  1167                                  	;mov	ebx, scounter		; (seconds counter)
  1168                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1169                                  ;	dec	byte [scounter+1]
  1170                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1171                                  ;	jns	short u_timer_retn
  1172                                  	; 26/02/2015
  1173                                  ;	call	rtc_p
  1174                                  ;	mov	ebx, scounter		; (seconds counter)
  1175                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1176                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1177                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1178                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1179                                  ;	mov	byte [ebx], 5
  1180                                  ;	inc	byte [ebx+1] ; 19
  1181                                  ;;timer_eoi:
  1182                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1183                                  ;;	out	20h, al	; 8259 PORT
  1184                                  	;
  1185                                  ;u_timer_retn:  ; 06/02/2015
  1186 00000773 5F                      	pop	edi
  1187 00000774 5E                      	pop	esi
  1188                                  	;pop	es
  1189                                  	;pop	ds
  1190                                  	;pop	ebx
  1191                                  	;pop	ecx
  1192                                  	;pop	edx
  1193                                  	;pop	eax
  1194                                  	;iret
  1195 00000775 C3                      	retn	; 06/02/2015
  1196                                  
  1197                                  	; 28/08/2014
  1198                                  irq0:
  1199 00000776 6A00                            push 	dword 0
  1200 00000778 EB48                    	jmp	short which_irq
  1201                                  irq1:
  1202 0000077A 6A01                            push 	dword 1
  1203 0000077C EB44                    	jmp	short which_irq
  1204                                  irq2:
  1205 0000077E 6A02                            push 	dword 2
  1206 00000780 EB40                    	jmp	short which_irq
  1207                                  irq3:
  1208                                  	; 20/11/2015
  1209                                  	; 24/10/2015
  1210 00000782 2EFF15[C2390000]        	call	dword [cs:com2_irq3]
  1211 00000789 6A03                    	push 	dword 3
  1212 0000078B EB35                    	jmp	short which_irq
  1213                                  irq4:
  1214                                  	; 20/11/2015
  1215                                  	; 24/10/2015
  1216 0000078D 2EFF15[BE390000]        	call	dword [cs:com1_irq4]
  1217 00000794 6A04                            push 	dword 4
  1218 00000796 EB2A                    	jmp	short which_irq
  1219                                  irq5:
  1220 00000798 6A05                            push 	dword 5
  1221 0000079A EB26                    	jmp	short which_irq
  1222                                  irq6:
  1223 0000079C 6A06                            push 	dword 6
  1224 0000079E EB22                    	jmp	short which_irq
  1225                                  irq7:
  1226 000007A0 6A07                            push 	dword 7
  1227 000007A2 EB1E                    	jmp	short which_irq
  1228                                  irq8:
  1229 000007A4 6A08                            push 	dword 8
  1230 000007A6 EB1A                    	jmp	short which_irq
  1231                                  irq9:
  1232 000007A8 6A09                            push 	dword 9
  1233 000007AA EB16                    	jmp	short which_irq
  1234                                  irq10:
  1235 000007AC 6A0A                            push 	dword 10
  1236 000007AE EB12                    	jmp	short which_irq
  1237                                  irq11:
  1238 000007B0 6A0B                            push 	dword 11
  1239 000007B2 EB0E                    	jmp	short which_irq
  1240                                  irq12:
  1241 000007B4 6A0C                            push 	dword 12
  1242 000007B6 EB0A                    	jmp	short which_irq
  1243                                  irq13:
  1244 000007B8 6A0D                            push 	dword 13
  1245 000007BA EB06                    	jmp	short which_irq
  1246                                  irq14:
  1247 000007BC 6A0E                            push 	dword 14
  1248 000007BE EB02                    	jmp	short which_irq
  1249                                  irq15:
  1250 000007C0 6A0F                            push 	dword 15
  1251                                  	;jmp	short which_irq
  1252                                  
  1253                                  	; 19/10/2015
  1254                                  	; 29/08/2014
  1255                                  	; 21/08/2014
  1256                                  which_irq:
  1257 000007C2 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1258 000007C5 53                      	push	ebx
  1259 000007C6 56                      	push	esi
  1260 000007C7 57                      	push	edi
  1261 000007C8 1E                      	push 	ds
  1262 000007C9 06                      	push 	es
  1263                                  	;
  1264 000007CA 88C3                    	mov	bl, al
  1265                                  	;
  1266 000007CC B810000000              	mov	eax, KDATA
  1267 000007D1 8ED8                    	mov	ds, ax
  1268 000007D3 8EC0                    	mov	es, ax
  1269                                  	; 19/10/2015
  1270 000007D5 FC                      	cld
  1271                                          ; 27/08/2014
  1272 000007D6 8105[D8670000]A000-             add     dword [scr_row], 0A0h
  1272 000007DE 0000               
  1273                                  	;
  1274 000007E0 B417                    	mov	ah, 17h	; blue (1) background, 
  1275                                  			; light gray (7) forecolor
  1276 000007E2 8B3D[D8670000]                  mov     edi, [scr_row]
  1277 000007E8 B049                    	mov	al, 'I'
  1278 000007EA 66AB                    	stosw
  1279 000007EC B052                    	mov	al, 'R'
  1280 000007EE 66AB                    	stosw
  1281 000007F0 B051                    	mov	al, 'Q'
  1282 000007F2 66AB                    	stosw
  1283 000007F4 B020                    	mov	al, ' '
  1284 000007F6 66AB                    	stosw
  1285 000007F8 88D8                    	mov	al, bl
  1286 000007FA 3C0A                    	cmp	al, 10
  1287 000007FC 7208                    	jb	short iix
  1288 000007FE B031                    	mov	al, '1'
  1289 00000800 66AB                    	stosw
  1290 00000802 88D8                    	mov	al, bl
  1291 00000804 2C0A                    	sub	al, 10
  1292                                  iix:
  1293 00000806 0430                    	add	al, '0'
  1294 00000808 66AB                    	stosw
  1295 0000080A B020                    	mov	al, ' '
  1296 0000080C 66AB                    	stosw
  1297 0000080E B021                    	mov	al, '!'
  1298 00000810 66AB                    	stosw
  1299 00000812 B020                    	mov	al, ' '
  1300 00000814 66AB                    	stosw
  1301                                  	; 23/02/2015
  1302 00000816 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1303                                  	;jna	iiret
  1304                                  	; 02/01/2022
  1305 00000819 7604                    	jna	short iiz
  1306                                  iiy:
  1307 0000081B B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1308 0000081D E6A0                    	out	0A0h, al ; the 2nd 8259
  1309                                  iiz:
  1310 0000081F E983010000              	jmp     iiret
  1311                                  	;
  1312                                  	; 22/08/2014
  1313                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1314                                  	;out	20h, al	; 8259 PORT
  1315                                  	;
  1316                                  	;pop	es
  1317                                  	;pop	ds
  1318                                  	;pop	edi
  1319                                  	;pop	esi
  1320                                  	;pop	ebx
  1321                                  	;pop 	eax
  1322                                  	;iret
  1323                                  
  1324                                  	; 02/04/2015
  1325                                  	; 25/08/2014
  1326                                  exc0:
  1327 00000824 6A00                            push 	dword 0
  1328 00000826 E990000000                      jmp     cpu_except
  1329                                  exc1:
  1330 0000082B 6A01                            push 	dword 1
  1331 0000082D E989000000                      jmp     cpu_except
  1332                                  exc2:
  1333 00000832 6A02                            push 	dword 2
  1334 00000834 E982000000                      jmp     cpu_except
  1335                                  exc3:
  1336 00000839 6A03                            push 	dword 3
  1337 0000083B EB7E                            jmp     cpu_except
  1338                                  exc4:
  1339 0000083D 6A04                            push 	dword 4
  1340 0000083F EB7A                            jmp     cpu_except
  1341                                  exc5:
  1342 00000841 6A05                            push 	dword 5
  1343 00000843 EB76                            jmp     cpu_except
  1344                                  exc6:
  1345 00000845 6A06                            push 	dword 6
  1346 00000847 EB72                            jmp     cpu_except
  1347                                  exc7:
  1348 00000849 6A07                            push 	dword 7
  1349 0000084B EB6E                            jmp     cpu_except
  1350                                  exc8:
  1351                                  	; [esp] = Error code
  1352 0000084D 6A08                            push 	dword 8
  1353 0000084F EB5C                            jmp     cpu_except_en
  1354                                  exc9:
  1355 00000851 6A09                            push 	dword 9
  1356 00000853 EB66                            jmp     cpu_except
  1357                                  exc10:
  1358                                  	; [esp] = Error code
  1359 00000855 6A0A                            push 	dword 10
  1360 00000857 EB54                            jmp     cpu_except_en
  1361                                  exc11:
  1362                                  	; [esp] = Error code
  1363 00000859 6A0B                            push 	dword 11
  1364 0000085B EB50                            jmp     cpu_except_en
  1365                                  exc12:
  1366                                  	; [esp] = Error code
  1367 0000085D 6A0C                            push 	dword 12
  1368 0000085F EB4C                            jmp     cpu_except_en
  1369                                  exc13:
  1370                                  	; [esp] = Error code
  1371 00000861 6A0D                            push 	dword 13
  1372 00000863 EB48                            jmp     cpu_except_en
  1373                                  exc14:
  1374                                  	; [esp] = Error code
  1375 00000865 6A0E                            push 	dword 14
  1376 00000867 EB44                    	jmp	short cpu_except_en
  1377                                  exc15:
  1378 00000869 6A0F                            push 	dword 15
  1379 0000086B EB4E                            jmp     cpu_except
  1380                                  exc16:
  1381 0000086D 6A10                            push 	dword 16
  1382 0000086F EB4A                            jmp     cpu_except
  1383                                  exc17:
  1384                                  	; [esp] = Error code
  1385 00000871 6A11                            push 	dword 17
  1386 00000873 EB38                    	jmp	short cpu_except_en
  1387                                  exc18:
  1388 00000875 6A12                            push 	dword 18
  1389 00000877 EB42                    	jmp	short cpu_except
  1390                                  exc19:
  1391 00000879 6A13                            push 	dword 19
  1392 0000087B EB3E                    	jmp	short cpu_except
  1393                                  exc20:
  1394 0000087D 6A14                            push 	dword 20
  1395 0000087F EB3A                    	jmp	short cpu_except
  1396                                  exc21:
  1397 00000881 6A15                            push 	dword 21
  1398 00000883 EB36                    	jmp	short cpu_except
  1399                                  exc22:
  1400 00000885 6A16                            push 	dword 22
  1401 00000887 EB32                    	jmp	short cpu_except
  1402                                  exc23:
  1403 00000889 6A17                            push 	dword 23
  1404 0000088B EB2E                    	jmp	short cpu_except
  1405                                  exc24:
  1406 0000088D 6A18                            push 	dword 24
  1407 0000088F EB2A                    	jmp	short cpu_except
  1408                                  exc25:
  1409 00000891 6A19                            push 	dword 25
  1410 00000893 EB26                    	jmp	short cpu_except
  1411                                  exc26:
  1412 00000895 6A1A                            push 	dword 26
  1413 00000897 EB22                    	jmp	short cpu_except
  1414                                  exc27:
  1415 00000899 6A1B                            push 	dword 27
  1416 0000089B EB1E                    	jmp	short cpu_except
  1417                                  exc28:
  1418 0000089D 6A1C                            push 	dword 28
  1419 0000089F EB1A                    	jmp	short cpu_except
  1420                                  exc29:
  1421 000008A1 6A1D                            push 	dword 29
  1422 000008A3 EB16                    	jmp	short cpu_except
  1423                                  exc30:
  1424 000008A5 6A1E                            push 	dword 30
  1425 000008A7 EB04                    	jmp	short cpu_except_en
  1426                                  exc31:
  1427 000008A9 6A1F                            push 	dword 31
  1428 000008AB EB0E                            jmp     short cpu_except
  1429                                  
  1430                                  	; 02/01/2022
  1431                                  	; 19/10/2015
  1432                                  	; 19/09/2015
  1433                                  	; 01/09/2015
  1434                                  	; 28/08/2015
  1435                                  	; 28/08/2014
  1436                                  cpu_except_en:
  1437 000008AD 87442404                	xchg	eax, [esp+4] ; Error code
  1438 000008B1 36A3[386D0000]          	mov	[ss:error_code], eax
  1439 000008B7 58                      	pop	eax  ; Exception number
  1440 000008B8 870424                  	xchg	eax, [esp]
  1441                                  		; eax = eax before exception
  1442                                  		; [esp] -> exception number
  1443                                  		; [esp+4] -> EIP to return
  1444                                  	; 19/10/2015
  1445                                  	; 19/09/2015
  1446                                  	; 01/09/2015
  1447                                  	; 28/08/2015
  1448                                  	; 29/08/2014
  1449                                  	; 28/08/2014
  1450                                  	; 25/08/2014
  1451                                  	; 21/08/2014
  1452                                  cpu_except:	; CPU Exceptions
  1453 000008BB FC                      	cld
  1454 000008BC 870424                  	xchg	eax, [esp] 
  1455                                  		; eax = Exception number
  1456                                  		; [esp] = eax (before exception)
  1457 000008BF 53                      	push	ebx
  1458 000008C0 56                      	push	esi
  1459 000008C1 57                      	push	edi
  1460 000008C2 1E                      	push 	ds
  1461 000008C3 06                      	push 	es
  1462                                  	; 28/08/2015
  1463 000008C4 66BB1000                	mov	bx, KDATA
  1464 000008C8 8EDB                    	mov	ds, bx
  1465 000008CA 8EC3                    	mov	es, bx
  1466 000008CC 0F20DB                  	mov	ebx, cr3
  1467 000008CF 53                      	push	ebx ; (*) page directory
  1468                                  	; 19/10/2015
  1469 000008D0 FC                      	cld
  1470                                  	; 25/03/2015
  1471 000008D1 8B1D[886C0000]          	mov	ebx, [k_page_dir]
  1472 000008D7 0F22DB                  	mov	cr3, ebx
  1473                                  	; 28/08/2015
  1474 000008DA 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1475 000008DD 7513                    	jne	short cpu_except_nfp
  1476 000008DF E87D270000              	call	page_fault_handler
  1477 000008E4 21C0                    	and 	eax, eax
  1478                                  	;jz	iiretp ; 01/09/2015
  1479                                  	; 02/01/2022
  1480 000008E6 7505                    	jnz	short cpu_except_pf
  1481 000008E8 E9B6000000              	jmp	iiretp
  1482                                  cpu_except_pf:
  1483 000008ED B80E000000              	mov	eax, 0Eh ; 14
  1484                                  cpu_except_nfp:
  1485                                  	; 02/04/2015
  1486 000008F2 BB[1B060000]            	mov	ebx, hang
  1487 000008F7 875C241C                	xchg	ebx, [esp+28]
  1488                                  		; EIP (points to instruction which faults)
  1489                                  	  	; New EIP (hang)
  1490 000008FB 891D[3C6D0000]          	mov	[FaultOffset], ebx
  1491 00000901 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1492 00000909 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1493                                  	;
  1494 00000911 88C4                    	mov	ah, al
  1495 00000913 240F                    	and	al, 0Fh
  1496 00000915 3C09                    	cmp	al, 9
  1497 00000917 7602                    	jna	short h1ok
  1498 00000919 0407                    	add	al, 'A'-':'
  1499                                  h1ok:
  1500 0000091B D0EC                    	shr	ah, 1
  1501 0000091D D0EC                    	shr	ah, 1
  1502 0000091F D0EC                    	shr	ah, 1
  1503 00000921 D0EC                    	shr	ah, 1
  1504 00000923 80FC09                  	cmp	ah, 9
  1505 00000926 7603                    	jna	short h2ok
  1506 00000928 80C407                  	add	ah, 'A'-':'
  1507                                  h2ok:	
  1508 0000092B 86E0                    	xchg 	ah, al	
  1509 0000092D 66053030                	add	ax, '00'
  1510 00000931 66A3[66680000]          	mov	[excnstr], ax
  1511                                  	;
  1512                                  	; 29/08/2014
  1513 00000937 A1[3C6D0000]            	mov	eax, [FaultOffset]
  1514 0000093C 51                      	push	ecx
  1515 0000093D 52                      	push	edx
  1516 0000093E 89E3                    	mov	ebx, esp
  1517                                  	; 28/08/2015
  1518 00000940 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1519                                  			  ; to hexadecimal string
  1520                                  	;mov	ecx, 10	    ; divisor to convert
  1521                                  			    ; binary number to decimal string
  1522                                  b2d1:
  1523 00000945 31D2                    	xor	edx, edx
  1524 00000947 F7F1                    	div	ecx
  1525                                  	;push	dx
  1526                                  	; 02/01/2022
  1527 00000949 52                      	push	edx
  1528 0000094A 39C8                    	cmp	eax, ecx
  1529 0000094C 73F7                    	jnb	short b2d1
  1530 0000094E BF[71680000]            	mov	edi, EIPstr ; EIP value
  1531                                  			    ; points to instruction which faults
  1532                                  	; 28/08/2015
  1533 00000953 89C2                    	mov	edx, eax
  1534                                  b2d2:
  1535                                  	;add	al, '0'
  1536 00000955 8A82[FD160000]          	mov	al, [edx+hexchrs]
  1537 0000095B AA                      	stosb		    ; write hexadecimal digit to its place
  1538 0000095C 39E3                    	cmp	ebx, esp
  1539 0000095E 7605                    	jna	short b2d3
  1540                                  	; 02/01/2022
  1541 00000960 58                      	pop	eax
  1542                                  	;pop	ax
  1543 00000961 88C2                    	mov	dl, al
  1544 00000963 EBF0                    	jmp	short b2d2
  1545                                  b2d3:
  1546 00000965 B068                    	mov 	al, 'h' ; 28/08/2015
  1547 00000967 AA                      	stosb
  1548 00000968 B020                    	mov	al, 20h	    ; space
  1549 0000096A AA                      	stosb
  1550 0000096B 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1551 0000096D AA                      	stosb
  1552                                  	;
  1553 0000096E 5A                      	pop	edx
  1554 0000096F 59                      	pop	ecx
  1555                                  	;
  1556 00000970 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1557                                  			; white (F) forecolor
  1558 00000972 BE[56680000]            	mov	esi, exc_msg ; message offset
  1559                                  	;
  1560 00000977 EB11                    	jmp	short piemsg
  1561                                  	;
  1562                                          ;add    dword [scr_row], 0A0h
  1563                                          ;mov    edi, [scr_row]
  1564                                          ;
  1565                                  	;call 	printk
  1566                                  	;
  1567                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1568                                  	;out	20h, al	; 8259 PORT
  1569                                  	;
  1570                                  	;pop	es
  1571                                  	;pop	ds
  1572                                  	;pop	edi
  1573                                  	;pop	esi
  1574                                  	;pop 	eax
  1575                                  	;iret
  1576                                  	
  1577                                  	; 28/08/2015
  1578                                  	; 23/02/2015
  1579                                  	; 20/08/2014
  1580                                  ignore_int:
  1581 00000979 50                      	push	eax
  1582 0000097A 53                      	push	ebx ; 23/02/2015
  1583 0000097B 56                      	push	esi
  1584 0000097C 57                      	push	edi
  1585 0000097D 1E                      	push 	ds
  1586 0000097E 06                      	push 	es
  1587                                  	; 28/08/2015
  1588 0000097F 0F20D8                  	mov	eax, cr3
  1589 00000982 50                      	push	eax ; (*) page directory
  1590                                  	;
  1591 00000983 B467                    	mov	ah, 67h	; brown (6) background, 
  1592                                  			; light gray (7) forecolor
  1593 00000985 BE[14680000]            	mov	esi, int_msg ; message offset
  1594                                  piemsg:
  1595                                          ; 27/08/2014
  1596 0000098A 8105[D8670000]A000-             add     dword [scr_row], 0A0h
  1596 00000992 0000               
  1597 00000994 8B3D[D8670000]                  mov     edi, [scr_row]
  1598                                          ;
  1599 0000099A E8B6FCFFFF              	call 	printk
  1600                                  	;
  1601                                  	; 23/02/2015
  1602 0000099F B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1603 000009A1 E6A0                    	out	0A0h, al ; the 2nd 8259
  1604                                  iiretp: ; 01/09/2015
  1605                                  	; 28/08/2015
  1606 000009A3 58                      	pop	eax ; (*) page directory
  1607 000009A4 0F22D8                  	mov	cr3, eax
  1608                                  	;
  1609                                  iiret:
  1610                                  	; 22/08/2014
  1611 000009A7 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1612 000009A9 E620                    	out	20h, al	; 8259 PORT
  1613                                  	;
  1614 000009AB 07                      	pop	es
  1615 000009AC 1F                      	pop	ds
  1616 000009AD 5F                      	pop	edi
  1617 000009AE 5E                      	pop	esi
  1618 000009AF 5B                      	pop	ebx ; 29/08/2014
  1619 000009B0 58                      	pop 	eax
  1620 000009B1 CF                      	iretd
  1621                                  
  1622                                  	; 26/02/2022
  1623                                  	; 26/02/2015
  1624                                  	; 07/09/2014
  1625                                  	; 25/08/2014
  1626                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1627                                  	; 22/08/2014
  1628 000009B2 50                      	push	eax
  1629 000009B3 53                      	push	ebx ; 29/08/2014
  1630 000009B4 56                      	push	esi
  1631 000009B5 57                      	push	edi
  1632 000009B6 1E                      	push 	ds
  1633 000009B7 06                      	push 	es
  1634                                  	;
  1635 000009B8 B810000000              	mov	eax, KDATA
  1636 000009BD 8ED8                    	mov	ds, ax
  1637 000009BF 8EC0                    	mov	es, ax
  1638                                  	;
  1639                                  	; 25/08/2014
  1640                                  	;call	rtc_p
  1641                                  	; 26/02/2022
  1642 000009C1 FF15[14070000]          	call	[x_rtci]
  1643                                  	;
  1644                                  	; 22/02/2015 - dsectpm.s
  1645                                  	; [ source: http://wiki.osdev.org/RTC ]
  1646                                  	; read status register C to complete procedure
  1647                                  	;(it is needed to get a next IRQ 8) 
  1648 000009C7 B00C                    	mov	al, 0Ch ; 
  1649 000009C9 E670                    	out	70h, al ; select register C
  1650 000009CB 90                      	nop
  1651 000009CC E471                    	in	al, 71h ; just throw away contents
  1652                                  	; 22/02/2015
  1653 000009CE B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1654 000009D0 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1655                                  	;
  1656 000009D2 EBD3                    	jmp	short iiret	
  1657                                  
  1658                                  	; 22/08/2014
  1659                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1660                                  	; (INT 1Ah)
  1661                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1662                                  time_of_day:
  1663 000009D4 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1664 000009D9 726F                            jc      short rtc_retn 
  1665 000009DB B000                    	mov	al, CMOS_SECONDS
  1666 000009DD E847010000              	call	CMOS_READ
  1667 000009E2 A2[FC6C0000]            	mov	[time_seconds], al 
  1668 000009E7 B002                    	mov	al, CMOS_MINUTES
  1669 000009E9 E83B010000              	call	CMOS_READ
  1670 000009EE A2[FD6C0000]            	mov	[time_minutes], al 
  1671 000009F3 B004                    	mov	al, CMOS_HOURS
  1672 000009F5 E82F010000              	call	CMOS_READ
  1673 000009FA A2[FE6C0000]                    mov     [time_hours], al
  1674 000009FF B006                    	mov	al, CMOS_DAY_WEEK 
  1675 00000A01 E823010000              	call	CMOS_READ
  1676 00000A06 A2[FF6C0000]            	mov	[date_wday], al
  1677 00000A0B B007                     	mov	al, CMOS_DAY_MONTH
  1678 00000A0D E817010000              	call	CMOS_READ
  1679 00000A12 A2[006D0000]            	mov	[date_day], al
  1680 00000A17 B008                    	mov	al, CMOS_MONTH
  1681 00000A19 E80B010000              	call	CMOS_READ
  1682 00000A1E A2[016D0000]            	mov	[date_month], al
  1683 00000A23 B009                    	mov	al, CMOS_YEAR
  1684 00000A25 E8FF000000              	call	CMOS_READ
  1685 00000A2A A2[026D0000]            	mov	[date_year], al
  1686 00000A2F B032                    	mov	al, CMOS_CENTURY
  1687 00000A31 E8F3000000              	call	CMOS_READ
  1688 00000A36 A2[036D0000]            	mov	[date_century], al
  1689                                  	;
  1690 00000A3B B000                    	mov	al, CMOS_SECONDS
  1691 00000A3D E8E7000000              	call 	CMOS_READ
  1692 00000A42 3A05[FC6C0000]          	cmp	al, [time_seconds]
  1693 00000A48 758A                    	jne	short time_of_day
  1694                                  
  1695                                  rtc_retn:
  1696 00000A4A C3                      	retn
  1697                                  
  1698                                  rtci_default:
  1699                                  	; 26/02/2022 (Temporary!)
  1700                                  	; (default real time clock handler in multitasking mode)
  1701                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1702 00000A4B FF05[446D0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1703                                  			; (not used in anywhere of kernel for now!)
  1704 00000A51 C3                      	retn
  1705                                  
  1706                                  rtc_p:	
  1707                                  	; 07/09/2014
  1708                                  	; 29/08/2014
  1709                                  	; 27/08/2014
  1710                                  	; 25/08/2014
  1711                                   	; Print Real Time Clock content
  1712                                  	;
  1713                                  	;
  1714 00000A52 E87DFFFFFF              	call	time_of_day
  1715 00000A57 72F1                    	jc	short rtc_retn
  1716                                  	;
  1717 00000A59 3A05[C8680000]          	cmp	al, [ptime_seconds]
  1718 00000A5F 74E9                            je      short rtc_retn ; 29/08/2014
  1719                                  	;
  1720 00000A61 A2[C8680000]            	mov	[ptime_seconds], al
  1721                                  	;
  1722 00000A66 A0[036D0000]            	mov	al, [date_century]
  1723 00000A6B E8EA000000              	call	bcd_to_ascii
  1724 00000A70 66A3[95680000]          	mov	[datestr+6], ax
  1725 00000A76 A0[026D0000]            	mov	al, [date_year]
  1726 00000A7B E8DA000000              	call	bcd_to_ascii
  1727 00000A80 66A3[97680000]          	mov	[datestr+8], ax
  1728 00000A86 A0[016D0000]            	mov	al, [date_month]
  1729 00000A8B E8CA000000              	call	bcd_to_ascii
  1730 00000A90 66A3[92680000]          	mov	[datestr+3], ax
  1731 00000A96 A0[006D0000]            	mov	al, [date_day]
  1732 00000A9B E8BA000000              	call	bcd_to_ascii
  1733 00000AA0 66A3[8F680000]          	mov	[datestr], ax
  1734                                  	;
  1735 00000AA6 0FB61D[FF6C0000]        	movzx	ebx, byte [date_wday]
  1736 00000AAD C0E302                  	shl 	bl, 2
  1737 00000AB0 81C3[A8680000]          	add	ebx, daytmp
  1738 00000AB6 8B03                    	mov	eax, [ebx]
  1739 00000AB8 A3[9A680000]            	mov	[daystr], eax
  1740                                  	;
  1741 00000ABD A0[FE6C0000]            	mov	al, [time_hours]
  1742 00000AC2 E893000000              	call	bcd_to_ascii
  1743 00000AC7 66A3[9E680000]          	mov	[timestr], ax
  1744 00000ACD A0[FD6C0000]            	mov	al, [time_minutes]
  1745 00000AD2 E883000000              	call	bcd_to_ascii
  1746 00000AD7 66A3[A1680000]          	mov	[timestr+3], ax
  1747 00000ADD A0[FC6C0000]            	mov	al, [time_seconds]
  1748 00000AE2 E873000000              	call	bcd_to_ascii
  1749 00000AE7 66A3[A4680000]          	mov	[timestr+6], ax
  1750                                  	;		
  1751 00000AED BE[7D680000]            	mov	esi, rtc_msg ; message offset
  1752                                  	; 23/02/2015
  1753 00000AF2 52                      	push	edx
  1754 00000AF3 51                      	push	ecx
  1755                                  	; 07/09/2014
  1756                                  	;mov	bx, 2	; Video page 2
  1757                                  	; 02/01/2022
  1758 00000AF4 29DB                    	sub	ebx, ebx
  1759 00000AF6 B307                    	mov	bl, 7	; Video page 7 
  1760                                  prtmsg:
  1761 00000AF8 AC                      	lodsb
  1762 00000AF9 08C0                    	or	al, al
  1763 00000AFB 740D                    	jz	short prtmsg_ok
  1764 00000AFD 56                      	push	esi
  1765                                  	; 02/01/2022
  1766 00000AFE 53                      	push	ebx
  1767                                  	;push	bx
  1768 00000AFF B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1769                                  			; white (F) forecolor
  1770 00000B01 E8BB080000              	call 	write_tty
  1771                                  	;pop	bx
  1772                                  	; 02/01/2022
  1773 00000B06 5B                      	pop	ebx
  1774 00000B07 5E                      	pop	esi
  1775 00000B08 EBEE                    	jmp	short prtmsg
  1776                                  	;
  1777                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1778                                  	;call	printk
  1779                                  prtmsg_ok:
  1780                                  	; 07/09/2014
  1781                                  	;xor	dx, dx		; column 0, row 0
  1782                                  	; 02/01/2022
  1783 00000B0A 31D2                    	xor	edx, edx
  1784 00000B0C E8BA090000              	call	set_cpos	; set curspor position to 0,0 
  1785                                  	; 23/02/2015
  1786 00000B11 59                      	pop	ecx
  1787 00000B12 5A                      	pop	edx
  1788 00000B13 C3                      	retn
  1789                                  
  1790                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1791                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1792                                  default_irq7:
  1793                                  	; 24/12/2021
  1794                                  	;push	ax
  1795 00000B14 50                      	push	eax
  1796 00000B15 B00B                    	mov	al, 0Bh  ; In-Service register
  1797 00000B17 E620                    	out	20h, al
  1798 00000B19 EB00                            jmp short $+2
  1799 00000B1B EB00                    	jmp short $+2
  1800 00000B1D E420                    	in	al, 20h
  1801 00000B1F 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1802 00000B21 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1803 00000B23 B020                            mov     al, 20h ; EOI
  1804 00000B25 E620                    	out	20h, al 
  1805                                  irq7_iret:
  1806                                  	;pop	ax
  1807                                  	; 24/12/2021
  1808 00000B27 58                      	pop	eax
  1809 00000B28 CF                      	iretd	
  1810                                  	
  1811                                  	; 24/12/2021
  1812                                  	; 22/08/2014
  1813                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1814                                  CMOS_READ:
  1815 00000B29 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1816 00000B2A D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1817 00000B2C F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1818 00000B2D D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1819 00000B2F FA                      	cli		; DISABLE INTERRUPTS
  1820 00000B30 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1821 00000B32 90                      	nop		; I/O DELAY
  1822 00000B33 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1823                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1824                                  	; 24/12/2021
  1825 00000B35 50                      	push	eax
  1826                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1827                                  		     ; ----- 10/06/85 (test4.asm)
  1828 00000B36 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1829                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1830 00000B38 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1831 00000B3A E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1832                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1833                                  	; 24/12/2021
  1834 00000B3C 58                      	pop	eax
  1835 00000B3D 9D                      	popf	
  1836 00000B3E C3                      	retn		; RETURN WITH FLAGS RESTORED
  1837                                  
  1838                                  	; 22/08/2014
  1839                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1840                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1841 00000B3F 51                      	push	ecx
  1842 00000B40 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1843                                  		; mov cx, 800	
  1844                                  UPD_10:
  1845 00000B45 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1846 00000B47 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1847 00000B48 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1848 00000B4D A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1849 00000B4F 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1850 00000B51 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1851 00000B52 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1852 00000B54 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1853                                  		; xor ax, ax
  1854 00000B56 F9                      	stc				; SET CARRY FOR ERROR
  1855                                  UPD_90:
  1856 00000B57 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1857 00000B58 FA                      	cli				; INTERRUPTS OFF DURING SET
  1858 00000B59 C3                      	retn				; RETURN WITH CY FLAG SET
  1859                                  
  1860                                  bcd_to_ascii:
  1861                                  	; 25/08/2014
  1862                                  	; INPUT ->
  1863                                  	;	al = Packed BCD number
  1864                                  	; OUTPUT ->
  1865                                  	;	ax  = ASCII word/number
  1866                                  	;
  1867                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1868                                  	;
  1869 00000B5A D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1870                                  					; AH = AL / 10h
  1871                                  					; AL = AL MOD 10h
  1872 00000B5C 660D3030                	or ax,'00'                      ; Make it ASCII based
  1873                                  
  1874 00000B60 86E0                            xchg ah, al 
  1875                                  	
  1876 00000B62 C3                      	retn	
  1877                                  	
  1878                                  
  1879                                  %include 'keyboard.inc' ; 07/03/2015
  1880                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KEYBOARD.INC
  1881                              <1> ; Last Modification: 13/06/2022
  1882                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1883                              <1> ;
  1884                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1885                              <1> 
  1886                              <1> ; 23/02/2022
  1887                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1888                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1889                              <1> ; 30/06/2015
  1890                              <1> ; 11/03/2015
  1891                              <1> ; 28/02/2015
  1892                              <1> ; 25/02/2015
  1893                              <1> ; 20/02/2015
  1894                              <1> ; 18/02/2015
  1895                              <1> ; 03/12/2014
  1896                              <1> ; 07/09/2014
  1897                              <1> ; KEYBOARD INTERRUPT HANDLER
  1898                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1899                              <1> 
  1900                              <1> ;getch:
  1901                              <1> ;	; 18/02/2015
  1902                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1903                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1904                              <1> ;	; routine, later... (multi tasking ability)
  1905                              <1> ;	; 28/02/2015
  1906                              <1> ;	sti	; enable interrupts
  1907                              <1> ;	;
  1908                              <1> ;	;push	esi
  1909                              <1> ;	;push	ebx
  1910                              <1> ;	;xor	ebx, ebx
  1911                              <1> ;	;mov	bl, [ptty]  ; active_page
  1912                              <1> ;	;mov	esi, ebx
  1913                              <1> ;	;shl 	si, 1
  1914                              <1> ;	;add	esi, ttychr
  1915                              <1> ;getch_1:
  1916                              <1> ;	;mov	ax, [esi]
  1917                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1918                              <1> ;	and	ax, ax
  1919                              <1> ;	jz	short getch_2
  1920                              <1> ;	mov	word [ttychr], 0
  1921                              <1> ;	;mov	word [esi], 0
  1922                              <1> ;	;pop	ebx
  1923                              <1> ;	;pop	esi
  1924                              <1> ;	retn
  1925                              <1> ;getch_2:
  1926                              <1> ;	hlt	; not proper for multi tasking!
  1927                              <1> ;		; (temporary halt for now)
  1928                              <1> ;		; 'sleep' on tty 
  1929                              <1> ;		; will (must) be located here		
  1930                              <1> ;	nop
  1931                              <1> ;	jmp	short getch_1
  1932                              <1> 
  1933                              <1> keyb_int:
  1934                              <1> 	; 23/02/2022
  1935                              <1> 	; 30/06/2015
  1936                              <1> 	; 25/02/2015
  1937                              <1> 	; 20/02/2015
  1938                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1939                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1940                              <1> 	; 30/06/2014
  1941                              <1> 	; 10/05/2013	
  1942                              <1>       	; Retro Unix 8086 v1 feature only!
  1943                              <1> 	; 03/03/2014
  1944                              <1> 	
  1945 00000B63 1E                  <1> 	push	ds
  1946 00000B64 53                  <1> 	push	ebx
  1947 00000B65 50                  <1> 	push	eax
  1948                              <1> 	;
  1949                              <1> 	; 23/02/2022
  1950 00000B66 9C                  <1> 	pushfd
  1951 00000B67 0E                  <1> 	push	cs
  1952                              <1> 	;mov	ax, KDATA
  1953 00000B68 31C0                <1> 	xor	eax, eax
  1954 00000B6A B010                <1> 	mov	al, KDATA
  1955 00000B6C 8ED8                <1> 	mov	ds, ax
  1956                              <1> 	;
  1957                              <1> 	;pushfd
  1958                              <1> 	;push	cs
  1959 00000B6E E810020000          <1> 	call	kb_int   ; int_09h
  1960                              <1> 	;
  1961 00000B73 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1962                              <1> 	;call	getc
  1963 00000B75 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1964 00000B7A 744E                <1> 	jz	short keyb_int4
  1965                              <1> 	;
  1966 00000B7C B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1967                              <1> 	;call	getc
  1968 00000B7E E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1969                              <1> 	;
  1970                              <1> 	; 20/02/2015
  1971 00000B83 0FB61D[B66C0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1972                              <1> 	;
  1973 00000B8A 20C0                <1> 	and 	al, al
  1974 00000B8C 751D                <1> 	jnz	short keyb_int1
  1975                              <1> 	;
  1976 00000B8E 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1977 00000B91 7218                <1> 	jb	short keyb_int1
  1978 00000B93 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1979 00000B96 7713                <1> 	ja	short keyb_int1
  1980                              <1> 	;
  1981 00000B98 88D8                <1> 	mov	al, bl
  1982 00000B9A 0468                <1> 	add	al, 68h
  1983 00000B9C 38E0                <1> 	cmp	al, ah
  1984 00000B9E 7409                <1> 	je	short keyb_int0
  1985 00000BA0 88E0                <1> 	mov	al, ah
  1986 00000BA2 2C68                <1> 	sub	al, 68h
  1987 00000BA4 E8370A0000          <1> 	call	tty_sw
  1988                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1989                              <1> keyb_int0: ; 30/06/2015
  1990                              <1> 	;xor	ax, ax
  1991                              <1> 	; 23/02/2022
  1992 00000BA9 31C0                <1> 	xor	eax, eax
  1993                              <1> keyb_int1:
  1994 00000BAB D0E3                <1> 	shl	bl, 1
  1995 00000BAD 81C3[B86C0000]      <1> 	add	ebx, ttychr
  1996                              <1> 	;
  1997                              <1> 	;23/02/2022
  1998 00000BB3 09C0                <1> 	or	eax, eax
  1999                              <1> 	;or	ax, ax
  2000 00000BB5 7406                <1> 	jz	short keyb_int2
  2001                              <1> 	;
  2002 00000BB7 66833B00            <1> 	cmp 	word [ebx], 0
  2003 00000BBB 7703                <1>         ja      short keyb_int3 
  2004                              <1> keyb_int2:
  2005 00000BBD 668903              <1>         mov	[ebx], ax  ; Save ascii code
  2006                              <1> 			   ; and scan code of the character
  2007                              <1> 			   ; for current tty (or last tty
  2008                              <1> 			   ; just before tty switch).
  2009                              <1> keyb_int3:
  2010 00000BC0 A0[B66C0000]        <1>         mov     al, [ptty]
  2011 00000BC5 E803440000          <1> 	call	wakeup
  2012                              <1> 	;
  2013                              <1> keyb_int4:
  2014 00000BCA 58                  <1> 	pop	eax
  2015 00000BCB 5B                  <1> 	pop	ebx
  2016 00000BCC 1F                  <1> 	pop	ds
  2017 00000BCD CF                  <1> 	iret
  2018                              <1> 
  2019                              <1> ; 18/02/2015
  2020                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2021                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2022                              <1> ; scancode and ascii code of the character 
  2023                              <1> ; in the tty input (ttychr) buffer. 
  2024                              <1> ; Test procedures must call 'getch' for tty input
  2025                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2026                              <1> ; due to infinite (key press) waiting loop.
  2027                              <1> ; 
  2028                              <1> ; 03/12/2014
  2029                              <1> ; 26/08/2014
  2030                              <1> ; KEYBOARD I/O
  2031                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2032                              <1> 
  2033                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2034                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2035                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2036                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2037                              <1> 
  2038                              <1> int_16h: ; 30/06/2015
  2039                              <1> ;getc:
  2040 00000BCE 9C                  <1> 	pushfd	; 28/08/2014
  2041 00000BCF 0E                  <1> 	push 	cs
  2042 00000BD0 E826000000          <1> 	call 	getc_int
  2043 00000BD5 C3                  <1> 	retn
  2044                              <1> 
  2045                              <1> ; 24/12/2021
  2046                              <1> 
  2047                              <1> 	;-----	SHIFT STATUS
  2048                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2049 00000BD6 8A25[B4660000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2050 00000BDC 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2051                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2052                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2053 00000BDF C0E405              <1>         shl	ah, 5
  2054 00000BE2 A0[B4660000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2055 00000BE7 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2056 00000BE9 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2057 00000BEB A0[B6660000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2058 00000BF0 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2059 00000BF2 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2060                              <1> _K3:
  2061 00000BF4 A0[B3660000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2062 00000BF9 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2063                              <1> 
  2064                              <1> getc_int:
  2065                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2066                              <1> 	; 28/02/2015
  2067                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2068                              <1> 	;	      instead of pc-at bios - 1985-)
  2069                              <1> 	; 28/08/2014 (_k1d)
  2070                              <1> 	; 30/06/2014
  2071                              <1> 	; 03/03/2014
  2072                              <1> 	; 28/02/2014
  2073                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2074                              <1> 	; rombios source code (21/04/1986)
  2075                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2076                              <1> 	;
  2077                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2078                              <1> 	;
  2079                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2080                              <1> 	; KEYBOARD I/O								      :
  2081                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2082                              <1> 	; INPUT									      :
  2083                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2084                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2085                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2086                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2087                              <1> 	;-----------------------------------------------------------------------------:
  2088                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2089                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2090                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2091                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2092                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2093                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2094                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2095                              <1> 	;-----------------------------------------------------------------------------:	
  2096                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2097                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2098                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2099                              <1> 	;-----------------------------------------------------------------------------:	
  2100                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2101                              <1> 	;	      (AL) = 05H                                                      :
  2102                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2103                              <1> 	;		       							      :
  2104                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2105                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2106                              <1> 	;                     --------------------------------------------            :
  2107                              <1> 	;			00H        30.0        10H        7.5                 :
  2108                              <1> 	;			01H        26.7        11H        6.7                 :
  2109                              <1> 	;			02H        24.0        12H        6.0                 :
  2110                              <1> 	;			03H        21.8        13H        5.5                 :
  2111                              <1> 	;			04H        20.0        14H        5.0                 :
  2112                              <1> 	;			05H        18.5        15H        4.6                 :
  2113                              <1> 	;			06H        17.1        16H        4.3                 :
  2114                              <1> 	;			07H        16.0        17H        4.0                 :
  2115                              <1> 	;			08H        15.0        18H        3.7                 :
  2116                              <1> 	;			09H        13.3        19H        3.3                 :
  2117                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2118                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2119                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2120                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2121                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2122                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2123                              <1> 	;									      :
  2124                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2125                              <1> 	;		       							      :
  2126                              <1> 	;                     REGISTER     DELAY                                      :
  2127                              <1> 	;                      VALUE       VALUE                                      :
  2128                              <1> 	;                     ------------------                                      :
  2129                              <1> 	;			00H        250 ms                                     :
  2130                              <1> 	;			01H        500 ms                                     :
  2131                              <1> 	;			02H        750 ms                                     :
  2132                              <1> 	;			03H       1000 ms                                     :
  2133                              <1> 	;-----------------------------------------------------------------------------:
  2134                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2135                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2136                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2137                              <1> 	;		           (CH) = SCAN CODE                                   :
  2138                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2139                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2140                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2141                              <1> 	;-----------------------------------------------------------------------------:		
  2142                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2143                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2144                              <1> 	;-----------------------------------------------------------------------------:
  2145                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2146                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2147                              <1> 	;-----------------------------------------------------------------------------:	
  2148                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2149                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2150                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2151                              <1> 	; OUTPUT					                              :
  2152                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2153                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2154                              <1> 	;------------------------------------------------------------------------------
  2155                              <1> 	
  2156 00000BFB FB                  <1> 	sti				; INTERRUPTS BACK ON
  2157 00000BFC 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2158 00000BFD 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2159                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2160 00000BFE 66BB1000            <1>         mov     bx, KDATA 
  2161 00000C02 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2162 00000C04 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2163 00000C06 742D                <1> 	jz	short _K1		; ASCII_READ
  2164 00000C08 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2165 00000C0A 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2166 00000C0C FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2167 00000C0E 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2168 00000C10 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2169 00000C12 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2170 00000C14 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2171 00000C17 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2172                              <1> _KIO1:	
  2173 00000C19 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2174 00000C1C 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2175 00000C1E FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2176 00000C20 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2177 00000C22 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2178 00000C24 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2179                              <1> _KIO_EXIT:
  2180                              <1> 	;pop	ecx			; RECOVER REGISTER
  2181 00000C26 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2182 00000C27 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2183 00000C28 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2184                              <1> 
  2185                              <1> 	;-----	ASCII CHARACTER
  2186                              <1> _K1E:	
  2187 00000C29 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2188 00000C2E E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2189 00000C33 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2190                              <1> _K1:	
  2191 00000C35 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2192 00000C3A E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2193 00000C3F 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2194                              <1> _K1A:
  2195 00000C41 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2196                              <1> 
  2197                              <1> 	;-----	ASCII STATUS
  2198                              <1> _K2E:	
  2199 00000C43 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2200 00000C48 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2201 00000C4A 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2202 00000C4B E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2203 00000C50 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2204                              <1> _K2:	
  2205 00000C52 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2206 00000C57 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2207 00000C59 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2208 00000C5A E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2209 00000C5F 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2210 00000C61 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2211 00000C62 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2212 00000C67 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2213                              <1> _K2A:
  2214 00000C69 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2215                              <1> _K2B:
  2216                              <1> 	;pop	ecx			; RECOVER REGISTER
  2217 00000C6A 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2218 00000C6B 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2219 00000C6C CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2220                              <1> 
  2221                              <1> ; 24/12/2021
  2222                              <1> ;	;-----	SHIFT STATUS
  2223                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2224                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2225                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2226                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2227                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2228                              <1> ;       shl	ah, 5
  2229                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2230                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2231                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2232                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2233                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2234                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2235                              <1> ;_K3:
  2236                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2237                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2238                              <1> 
  2239                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2240                              <1> _K300:
  2241 00000C6F 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2242 00000C71 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2243 00000C73 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2244 00000C76 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2245 00000C78 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2246 00000C7B 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2247 00000C7D B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2248 00000C7F E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2249                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2250                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2251 00000C84 C0E705              <1> 	shl	bh, 5
  2252 00000C87 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2253 00000C89 08F8                <1> 	or	al, bh			; AND DELAY
  2254 00000C8B E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2255 00000C90 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2256                              <1> 
  2257                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2258                              <1> _K500:
  2259 00000C92 56                  <1> 	push	esi			; SAVE SI (esi)
  2260 00000C93 FA                  <1> 	cli				; 
  2261 00000C94 8B1D[C4660000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2262 00000C9A 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2263 00000C9C E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2264 00000CA1 3B1D[C0660000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2265 00000CA7 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2266 00000CA9 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2267 00000CAC 891D[C4660000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2268 00000CB2 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2269 00000CB4 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2270                              <1> _K502:
  2271 00000CB6 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2272                              <1> _K504:
  2273 00000CB8 FB                  <1> 	sti				
  2274 00000CB9 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2275 00000CBA E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2276                              <1> 
  2277                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2278                              <1> _K1S:
  2279 00000CBF FA                  <1> 	cli	; 03/12/2014
  2280 00000CC0 8B1D[C0660000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2281 00000CC6 3B1D[C4660000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2282                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2283 00000CCC 750F                <1> 	jne	short _k1x ; 03/12/2014
  2284                              <1> 	;
  2285                              <1> 	; 03/12/2014
  2286                              <1> 	; 28/08/2014
  2287                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2288                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2289                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2290                              <1> _K1T:                                   ; ASCII READ
  2291 00000CCE FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2292 00000CCF 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2293                              <1> _K1U:	
  2294 00000CD0 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2295 00000CD1 8B1D[C0660000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2296 00000CD7 3B1D[C4660000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2297                              <1> _k1x:
  2298 00000CDD 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2299 00000CDE 9C                  <1> 	pushf				; SAVE FLAGS
  2300 00000CDF E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2301 00000CE4 8A1D[B5660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2302 00000CEA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2303 00000CEC 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2304 00000CEF 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2305 00000CF1 E86A060000          <1> 	call	SND_LED1
  2306 00000CF6 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2307                              <1> _K1V:
  2308 00000CF7 9D                  <1> 	popf				; RESTORE FLAGS
  2309 00000CF8 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2310 00000CF9 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2311                              <1> 	;
  2312 00000CFB 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2313 00000CFE E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2314 00000D03 891D[C0660000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2315 00000D09 C3                  <1> 	retn				; RETURN
  2316                              <1> 
  2317                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2318                              <1> _K2S:
  2319 00000D0A FA                  <1> 	cli				; INTERRUPTS OFF
  2320 00000D0B 8B1D[C0660000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2321 00000D11 3B1D[C4660000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2322 00000D17 668B03              <1> 	mov	ax, [ebx]
  2323 00000D1A 9C                  <1> 	pushf				; SAVE FLAGS
  2324                              <1> 	;push	ax			; SAVE CODE
  2325                              <1> 	; 24/12/2021
  2326 00000D1B 50                  <1> 	push	eax
  2327 00000D1C E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2328 00000D21 8A1D[B5660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2329 00000D27 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2330 00000D29 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2331 00000D2C 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2332 00000D2E E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2333                              <1> _K2T:
  2334                              <1> 	;pop	ax			; RESTORE CODE
  2335                              <1> 	; 24/12/2021
  2336 00000D33 58                  <1> 	pop	eax
  2337 00000D34 9D                  <1> 	popf				; RESTORE FLAGS
  2338 00000D35 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2339 00000D36 C3                  <1> 	retn				; RETURN
  2340                              <1> 
  2341                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2342                              <1> _KIO_E_XLAT:
  2343 00000D37 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2344 00000D39 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2345 00000D3B 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2346 00000D3D 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2347 00000D3F 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2348                              <1> _KIO_E_RET:				
  2349 00000D41 C3                  <1> 	retn				; GO BACK
  2350                              <1> 
  2351                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2352                              <1> _KIO_S_XLAT:
  2353 00000D42 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2354 00000D45 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2355 00000D47 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2356 00000D49 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2357 00000D4B 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2358 00000D4D 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2359 00000D4F B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2360                              <1> _kio_ret: ; 03/12/2014
  2361 00000D51 F8                  <1> 	clc
  2362 00000D52 C3                  <1> 	retn
  2363                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2364                              <1> _KIO_S1:				
  2365 00000D53 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2366                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2367 00000D55 C3                  <1> 	retn
  2368                              <1> _KIO_S2:		
  2369 00000D56 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2370 00000D59 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2371 00000D5B 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2372 00000D5D 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2373 00000D5F 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2374 00000D61 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2375 00000D63 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2376                              <1> _KIO_S3:
  2377 00000D65 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2378                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2379 00000D67 75E8                <1> 	jne	short _kio_ret
  2380 00000D69 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2381 00000D6B 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2382 00000D6D 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2383                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2384                              <1> _KIO_USE:
  2385                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2386 00000D6F C3                  <1> 	retn				; RETURN	
  2387                              <1> _KIO_DIS:
  2388 00000D70 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2389 00000D71 C3                  <1> 	retn				; RETURN
  2390                              <1> 
  2391                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2392                              <1> _K4:    
  2393 00000D72 43                  <1> 	inc     ebx
  2394 00000D73 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2395 00000D74 3B1D[BC660000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2396                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2397 00000D7A 7206                <1> 	jb	short _K5
  2398 00000D7C 8B1D[B8660000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2399                              <1> _K5:
  2400 00000D82 C3                  <1> 	retn
  2401                              <1> 
  2402                              <1> ; 20/02/2015
  2403                              <1> ; 05/12/2014
  2404                              <1> ; 26/08/2014
  2405                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2406                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2407                              <1> ;
  2408                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2409                              <1> ; rombios source code (06/10/1985)
  2410                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2411                              <1> 
  2412                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2413                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2414                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2415                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2416                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2417                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2418                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2419                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2420                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2421                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2422                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2423                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2424                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2425                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2426                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2427                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2428                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2429                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2430                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2431                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2432                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2433                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2434                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2435                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2436                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2437                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2438                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2439                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2440                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2441                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2442                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2443                              <1> F11_M		equ	87		; F11 KEY MAKE
  2444                              <1> F12_M		equ	88		; F12 KEY MAKE
  2445                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2446                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2447                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2448                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2449                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2450                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2451                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2452                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2453                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2454                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2455                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2456                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2457                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2458                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2459                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2460                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2461                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2462                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2463                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2464                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2465                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2466                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2467                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2468                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2469                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2470                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2471                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2472                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2473                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2474                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2475                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2476                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2477                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2478                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2479                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2480                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2481                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2482                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2483                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2484                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2485                              <1> ;
  2486                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2487                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2488                              <1> INTA00		equ	020h		; 8259 PORT
  2489                              <1> 
  2490                              <1> 
  2491                              <1> kb_int:
  2492                              <1> 
  2493                              <1> ; 13/06/2022
  2494                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2495                              <1> ; 17/10/2015 ('ctrlbrk') 
  2496                              <1> ; 05/12/2014
  2497                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2498                              <1> 	;	      instead of pc-at bios - 1985-)
  2499                              <1> ; 26/08/2014
  2500                              <1> ;
  2501                              <1> ; 03/06/86  KEYBOARD BIOS
  2502                              <1> ;
  2503                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2504                              <1> ;										;
  2505                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2506                              <1> ;										;
  2507                              <1> ;--------------------------------------------------------------------------------
  2508                              <1> 
  2509                              <1> KB_INT_1:
  2510 00000D83 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2511                              <1> 	;push	ebp
  2512 00000D84 50                  <1> 	push	eax
  2513 00000D85 53                  <1> 	push	ebx
  2514 00000D86 51                  <1> 	push	ecx
  2515 00000D87 52                  <1> 	push	edx
  2516 00000D88 56                  <1> 	push	esi
  2517 00000D89 57                  <1> 	push	edi
  2518 00000D8A 1E                  <1> 	push	ds
  2519 00000D8B 06                  <1> 	push	es
  2520 00000D8C FC                  <1> 	cld				; FORWARD DIRECTION
  2521 00000D8D 66B81000            <1> 	mov	ax, KDATA
  2522 00000D91 8ED8                <1> 	mov	ds, ax
  2523 00000D93 8EC0                <1> 	mov	es, ax
  2524                              <1> 	;
  2525                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2526 00000D95 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2527 00000D97 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2528 00000D9C FA                  <1> 	cli				; DISABLE INTERRUPTS
  2529 00000D9D B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2530                              <1> KB_INT_01:
  2531 00000DA2 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2532 00000DA4 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2533 00000DA6 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2534                              <1> 	;
  2535                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2536 00000DA8 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2537                              <1> 	;
  2538                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2539                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2540                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2541                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2542                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2543                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2544                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2545                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2546                              <1> 	;
  2547                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2548                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2549 00000DAA FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2550 00000DAB 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2551 00000DAD 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2552                              <1> 	;
  2553                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2554 00000DAF 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2555 00000DB1 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2556                              <1> 	;
  2557                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2558 00000DB3 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2559 00000DB4 800D[B5660000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2560 00000DBB E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2561                              <1> 	;
  2562                              <1> 	;-----	RESEND THE LAST BYTE
  2563                              <1> KB_INT_4:
  2564 00000DC0 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2565 00000DC1 800D[B5660000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2566 00000DC8 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2567                              <1> 	;
  2568                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2569                              <1> KB_INT_2:
  2570                              <1> 	;push 	ax			; SAVE DATA IN
  2571                              <1> 	; 24/12/2021
  2572 00000DCD 50                  <1> 	push	eax
  2573 00000DCE E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2574 00000DD3 8A1D[B5660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2575 00000DD9 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2576 00000DDB 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2577 00000DDE 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2578 00000DE0 E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2579                              <1> UP0:
  2580                              <1> 	;pop	ax			; RESTORE DATA IN
  2581                              <1> 	; 24/12/2021
  2582 00000DE5 58                  <1> 	pop	eax
  2583                              <1> ;------------------------------------------------------------------------
  2584                              <1> ;	START OF KEY PROCESSING						;
  2585                              <1> ;------------------------------------------------------------------------
  2586 00000DE6 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2587                              <1> 	;
  2588                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2589 00000DE8 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2590                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2591                              <1> 	; 24/12/2021
  2592 00000DEA 7505                <1> 	jne	short K16
  2593 00000DEC E9E9040000          <1> 	jmp	K62
  2594                              <1> K16:	
  2595 00000DF1 8A3D[B6660000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2596                              <1> 	;
  2597                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2598 00000DF7 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2599 00000DFA 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2600 00000DFC 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2601 00000DFE 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2602 00000E00 7507                <1> 	jne	short RST_RD_ID
  2603 00000E02 800D[B6660000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2604                              <1> RST_RD_ID:
  2605 00000E09 8025[B6660000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2606 00000E10 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2607                              <1> 	; 24/12/2021
  2608                              <1> 	;jmp	K26
  2609                              <1> 	;
  2610                              <1> TST_ID_2:
  2611 00000E12 8025[B6660000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2612 00000E19 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2613 00000E1B 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2614 00000E1D 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2615 00000E1F 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2616                              <1> 	; 24/12/2021
  2617                              <1> 	;jne	K26
  2618                              <1> 	;
  2619                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2620 00000E21 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2621 00000E24 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2622 00000E26 800D[B3660000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2623 00000E2D E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2624                              <1> KX_BIT:
  2625 00000E32 800D[B6660000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2626 00000E39 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2627                              <1> 	;
  2628                              <1> NOT_ID:
  2629 00000E3E 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2630 00000E40 750E                <1> 	jne	short TEST_E1
  2631 00000E42 800D[B6660000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2632 00000E49 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2633                              <1> 	; 24/12/2021
  2634 00000E4B E9DA010000          <1> 	jmp	K26A	
  2635                              <1> TEST_E1:	
  2636 00000E50 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2637 00000E52 750C                <1> 	jne	short NOT_HC
  2638 00000E54 800D[B6660000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2639 00000E5B E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2640                              <1> 	;
  2641                              <1> NOT_HC:
  2642 00000E60 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2643 00000E62 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2644 00000E65 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2645                              <1> 	;
  2646 00000E67 BF[9E650000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2647 00000E6C AE                  <1> 	scasb
  2648                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2649                              <1> 	; 24/12/2021
  2650 00000E6D 7458                <1> 	je	short K16B
  2651 00000E6F AE                  <1> 	scasb
  2652 00000E70 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2653 00000E72 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2654                              <1> 	; 24/12/2021
  2655                              <1> 	;jmp	K26
  2656                              <1> 	;
  2657                              <1> NOT_LC_E0:
  2658 00000E74 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2659 00000E77 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2660 00000E79 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2661 00000E7E BF[9C650000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2662 00000E83 F2AE                <1> 	repne	scasb			; CHECK IT
  2663 00000E85 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2664                              <1> 	; 24/12/2021
  2665                              <1> 	;je	K26A			
  2666                              <1> 	;
  2667 00000E87 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2668 00000E89 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2669                              <1> 	; 24/12/2021
  2670                              <1> 	;jne	K26
  2671 00000E8B F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2672 00000E8E 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2673                              <1> 	; 24/12/2021
  2674                              <1> 	;jnz	K26
  2675                              <1>         ; 20/02/2015 
  2676 00000E90 F605[B4660000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2677 00000E97 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2678                              <1> 	; 24/12/2021
  2679                              <1> 	;jnz	K26
  2680 00000E99 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2681                              <1> 	;
  2682                              <1> 	;-----	TEST FOR SYSTEM KEY
  2683                              <1> T_SYS_KEY:
  2684 00000E9E 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2685 00000EA0 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2686                              <1> 	;
  2687 00000EA2 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2688 00000EA5 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2689                              <1> 	;
  2690 00000EA7 F605[B4660000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2691 00000EAE 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2692                              <1> 	;jnz	K26			
  2693                              <1> 	;
  2694 00000EB0 800D[B4660000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2695 00000EB7 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2696 00000EB9 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2697                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2698 00000EBB B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2699 00000EBD E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2700                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2701                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2702                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2703                              <1> 	;INT	15H			; USER INTERRUPT	
  2704 00000EC2 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2705                              <1> 	;
  2706 00000EC7 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2707                              <1> 	;
  2708                              <1> K16C:
  2709 00000ECC 8025[B4660000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2710 00000ED3 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2711 00000ED5 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2712                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2713                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2714                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2715                              <1> 	;
  2716                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2717                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2718                              <1> 	;INT	15H			; USER INTERRUPT
  2719                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2720                              <1> 	;
  2721 00000ED7 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2722                              <1> 	;
  2723                              <1> 	;-----	TEST FOR SHIFT KEYS
  2724                              <1> K16A:
  2725 00000EDC 8A1D[B3660000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2726 00000EE2 BF[98650000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2727 00000EE7 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2728 00000EEC F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2729 00000EEE 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2730                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2731                              <1> 	; 24/12/2021
  2732 00000EF0 7405                <1> 	je	short K17
  2733 00000EF2 E914010000          <1> 	jmp	K25
  2734                              <1> 	;
  2735                              <1> 	;------	SHIFT KEY FOUND
  2736                              <1> K17:
  2737 00000EF7 81EF[99650000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2738 00000EFD 8AA7[A0650000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2739 00000F03 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2740 00000F05 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2741                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2742                              <1> 	; 24/12/2021
  2743 00000F07 7405                <1> 	jz	short K17C
  2744 00000F09 E999000000          <1> 	jmp	K23
  2745                              <1> 	;
  2746                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2747                              <1> K17C:
  2748 00000F0E 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2749 00000F11 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2750                              <1> 	;
  2751                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2752 00000F13 0825[B3660000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2753 00000F19 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2754 00000F1B 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2755                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2756                              <1> 	; 24/12/2021
  2757 00000F1D E901010000          <1> 	jmp	K26
  2758                              <1> K17D:
  2759 00000F22 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2760 00000F25 740B                <1> 	jz 	short K17E		; NO, JUMP
  2761 00000F27 0825[B6660000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2762 00000F2D E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2763                              <1> K17E:
  2764 00000F32 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2765 00000F34 0825[B4660000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2766 00000F3A E9E4000000          <1> 	jmp	K26
  2767                              <1> 	;
  2768                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2769                              <1> K18:					; SHIFT-TOGGLE
  2770 00000F3F F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2771 00000F42 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2772                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2773                              <1> 	; 24/12/2021
  2774 00000F44 E9C2000000          <1> 	jmp	K25
  2775                              <1> K18A:
  2776 00000F49 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2777 00000F4B 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2778 00000F4D F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2779 00000F50 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2780                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2781                              <1> 	; 24/12/2021
  2782 00000F52 E9B4000000          <1> 	jmp	K25
  2783                              <1> K18B:
  2784 00000F57 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2785 00000F5A 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2786                              <1> K19:	
  2787 00000F5C F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2788 00000F5F 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2789 00000F61 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2790 00000F64 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2791                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2792 00000F66 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2793 00000F68 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2794                              <1> K21:					; MIGHT BE NUMERIC
  2795 00000F6D F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2796 00000F70 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2797                              <1> 	;
  2798                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2799 00000F72 8425[B4660000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2800                              <1> 	;jnz	K26
  2801                              <1> 	; 24/12/2021
  2802 00000F78 7405                <1> 	jz	short K22A
  2803 00000F7A E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2804                              <1> K22A:
  2805 00000F7F 0825[B4660000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2806 00000F85 3025[B3660000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2807                              <1> 	;
  2808                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2809 00000F8B F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2810 00000F8E 7407                <1> 	jz	short K22B		; GO IF NOT
  2811                              <1> 	;
  2812                              <1> 	; 24/12/2021
  2813                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2814 00000F90 50                  <1> 	push	eax
  2815 00000F91 E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2816                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2817 00000F96 58                  <1> 	pop	eax
  2818                              <1> K22B:
  2819 00000F97 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2820                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2821                              <1> 	; 24/12/2021
  2822 00000F99 7405                <1> 	je	short K22C
  2823 00000F9B E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2824                              <1> K22C:
  2825 00000FA0 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2826 00000FA2 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2827                              <1> 	;
  2828                              <1> 	;-----	BREAK SHIFT FOUND
  2829                              <1> K23:					; BREAK-SHIFT-FOUND
  2830 00000FA7 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2831 00000FAA F6D4                <1> 	not	ah			; INVERT MASK
  2832 00000FAC 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2833 00000FAE 2025[B3660000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2834 00000FB4 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2835 00000FB7 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2836                              <1> 	;
  2837 00000FB9 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2838 00000FBC 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2839 00000FBE 2025[B6660000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2840 00000FC4 EB08                <1> 	jmp	short K23B		; CONTINUE
  2841                              <1> K23A:
  2842 00000FC6 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2843 00000FC8 2025[B4660000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2844                              <1> K23B:
  2845 00000FCE 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2846 00000FD0 A0[B6660000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2847 00000FD5 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2848 00000FD7 0A05[B4660000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2849 00000FDD D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2850 00000FDF 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2851 00000FE1 0805[B3660000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2852 00000FE7 88E0                <1> 	mov	al, ah
  2853                              <1> K23D:
  2854 00000FE9 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2855 00000FEB 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2856                              <1> 	;	
  2857                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2858 00000FED A0[B7660000]        <1> 	mov	al, [ALT_INPUT]
  2859 00000FF2 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2860 00000FF4 8825[B7660000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2861 00000FFA 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2862 00000FFC 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2863 00000FFE E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2864                              <1> 	;
  2865                              <1> K24:					; BREAK-TOGGLE
  2866 00001003 2025[B4660000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2867 00001009 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2868                              <1> 	;
  2869                              <1> 	;-----	TEST FOR HOLD STATE
  2870                              <1> 					; AL, AH = SCAN CODE
  2871                              <1> K25:					; NO-SHIFT-FOUND
  2872 0000100B 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2873 0000100D 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2874 0000100F F605[B4660000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2875 00001016 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2876 00001018 3C45                <1> 	cmp	al, NUM_KEY
  2877 0000101A 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2878 0000101C 8025[B4660000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2879                              <1> 	;
  2880                              <1> K26:
  2881 00001023 8025[B6660000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2882                              <1> K26A:					; INTERRUPT-RETURN
  2883 0000102A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2884 0000102B B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2885 0000102D E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2886                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2887 0000102F B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2888 00001031 E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2889                              <1> K27A:
  2890 00001036 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2891 00001037 07                  <1> 	pop	es			; RESTORE REGISTERS
  2892 00001038 1F                  <1> 	pop	ds
  2893 00001039 5F                  <1> 	pop	edi
  2894 0000103A 5E                  <1> 	pop	esi
  2895 0000103B 5A                  <1> 	pop	edx
  2896 0000103C 59                  <1> 	pop	ecx
  2897 0000103D 5B                  <1> 	pop	ebx
  2898 0000103E 58                  <1> 	pop	eax
  2899                              <1> 	;pop	ebp
  2900 0000103F CF                  <1> 	iret				; RETURN
  2901                              <1> 
  2902                              <1> 	;-----	NOT IN	HOLD STATE
  2903                              <1> K28:					; NO-HOLD-STATE
  2904 00001040 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2905 00001042 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2906                              <1> 	;
  2907 00001044 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2908 00001047 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2909                              <1>         ; 24/12/2021
  2910                              <1> 	;jz      K38
  2911                              <1> 	;
  2912 00001049 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2913 0000104C 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2914                              <1> 	; 28/02/2015
  2915 0000104E F605[B4660000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2916 00001055 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2917                              <1> 	; 24/12/2021
  2918                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2919                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2920 00001057 E9CD000000          <1> K28A:	jmp	K38
  2921                              <1> 	;
  2922                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2923                              <1> K29:					; TEST-RESET
  2924 0000105C F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2925 0000105F 740B                <1> 	jz	short K31		; NO_RESET
  2926 00001061 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2927 00001063 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2928                              <1> 	;
  2929                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2930                              <1>  	; 26/08/2014
  2931                              <1> cpu_reset:
  2932                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2933                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2934 00001065 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2935 00001067 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2936                              <1> khere:
  2937 00001069 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2938 0000106A EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2939                              <1> 
  2940                              <1> 	;
  2941                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2942                              <1> K31:					; NO-RESET
  2943 0000106C 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2944 0000106E 7507                <1> 	jne	short K311		; NOT THERE
  2945 00001070 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2946 00001072 E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2947                              <1> K311:
  2948 00001077 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2949 00001079 7509                <1> 	jne	short K312		; NOT THERE
  2950 0000107B 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2951 0000107F E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2952                              <1> K312:
  2953 00001084 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2954 00001086 7471                <1>         je	short K37B              ; GO PROCESS
  2955 00001088 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2956 0000108A 746D                <1>         je	short K37B              ; GO PROCESS
  2957                              <1> 	;
  2958                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2959                              <1> K32:					; ALT-KEY-PAD
  2960 0000108C BF[74650000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2961 00001091 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2962 00001096 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2963 00001098 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2964 0000109A F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2965                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2966                              <1> 	; 24/12/2021
  2967 0000109D 751C                <1> 	jnz	short K32B
  2968 0000109F 81EF[75650000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2969 000010A5 A0[B7660000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2970 000010AA B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2971 000010AC F6E4                <1> 	mul	ah
  2972 000010AE 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2973 000010B1 A2[B7660000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2974                              <1> K32A:
  2975 000010B6 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2976                              <1> K32B:
  2977                              <1> 	; 24/12/2021
  2978 000010BB EB66                <1> 	jmp	K37C
  2979                              <1> 	;
  2980                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2981                              <1> K33:					; NO-ALT-KEYPAD
  2982 000010BD C605[B7660000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2983 000010C4 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2984 000010C9 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2985 000010CB 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2986                              <1> 	;
  2987                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2988                              <1> K34:					; ALT-TOP-ROW
  2989 000010CD 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2990 000010CF 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2991 000010D1 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2992 000010D3 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2993 000010D5 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2994 000010D8 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2995                              <1> 	;
  2996                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2997                              <1> K35:					; ALT-FUNCTION
  2998 000010DA 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2999 000010DC 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  3000 000010DE 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  3001 000010E0 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  3002 000010E2 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  3003 000010E5 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3004                              <1> K35A:
  3005 000010E7 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  3006 000010EA 7425                <1> 	jz	short K37		; NO, JUMP
  3007 000010EC 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3008 000010EE 7510                <1>         jne     short K35B              ; NOT THERE
  3009 000010F0 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3010 000010F4 E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  3011                              <1> K37B:
  3012 000010F9 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3013 000010FB E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3014                              <1> K35B:
  3015 00001100 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3016 00001102 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3017 00001104 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3018 00001106 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3019                              <1>         ; 24/12/2021
  3020                              <1> 	;jne	K26
  3021 00001108 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3022 0000110C E998010000          <1> 	jmp	K57			; BUFFER FILL
  3023                              <1> K37:
  3024 00001111 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3025 00001113 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3026 00001115 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3027 00001117 779D                <1>         ja	short K32A		; IF SO, IGNORE
  3028                              <1> 	; 13/06/2022
  3029                              <1>         ;ja	K26
  3030 00001119 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3031                              <1> K37A:
  3032 0000111C B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3033 0000111E E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3034                              <1> K37C:
  3035 00001123 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3036 00001125 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3037 00001127 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3038                              <1> 	;
  3039                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3040                              <1> K38:					; NOT-ALT-SHIFT
  3041                              <1> 					; BL STILL HAS SHIFT FLAGS
  3042 00001129 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3043 0000112C 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3044                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3045                              <1> 	; 24/12/2021
  3046 0000112E E9AB000000          <1> 	jmp	K44
  3047                              <1> 	;
  3048                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3049                              <1> 	;-----	TEST FOR BREAK
  3050                              <1> K38A:
  3051 00001133 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3052 00001135 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3053 00001137 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3054 0000113A 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3055 0000113C F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3056 0000113F 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3057                              <1> K38B:
  3058 00001141 8B1D[C0660000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3059 00001147 891D[C4660000]      <1> 	mov	[BUFFER_TAIL], ebx
  3060 0000114D C605[B2660000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3061                              <1> 	;
  3062                              <1> 	;-----	ENABLE KEYBOARD
  3063 00001154 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3064 00001156 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3065                              <1> 	;
  3066                              <1> 	; CTRL+BREAK code here !!!
  3067                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3068                              <1> 	; 17/10/2015	
  3069 0000115B E858220000          <1> 	call	ctrlbrk ; control+break subroutine
  3070                              <1> 	;
  3071                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3072                              <1> 	; 24/12/2021
  3073 00001160 29C0                <1> 	sub	eax, eax
  3074 00001162 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3075                              <1> 	;
  3076                              <1> 	;-----	TEST FOR PAUSE
  3077                              <1> K39:					; NO_BREAK
  3078 00001167 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3079 0000116A 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3080 0000116C 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3081 0000116E 7533                <1> 	jne	short K41		; NO-PAUSE
  3082                              <1> K39P:
  3083 00001170 800D[B4660000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3084                              <1> 	;
  3085                              <1> 	;-----	ENABLE KEYBOARD
  3086 00001177 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3087 00001179 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3088                              <1> K39A:
  3089 0000117E B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3090 00001180 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3091                              <1> 	;
  3092                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3093 00001182 803D[B0660000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3094 00001189 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3095 0000118B 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3096 0000118F A0[B1660000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3097 00001194 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3098                              <1> 	;
  3099                              <1> K40:					; PAUSE-LOOP
  3100 00001195 F605[B4660000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3101 0000119C 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3102                              <1> 	;
  3103 0000119E E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3104                              <1>         ;
  3105                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3106                              <1> K41:					; NO-PAUSE
  3107 000011A3 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3108 000011A5 7513                <1> 	jne	short K42		; NOT-KEY-55
  3109 000011A7 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3110 000011AA 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3111 000011AC F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3112 000011AF 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3113                              <1> K41A:	
  3114 000011B1 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3115 000011B5 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3116                              <1> 	;
  3117                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3118                              <1> K42:					; NOT-KEY-55
  3119 000011BA 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3120 000011BC 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3121 000011BE 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3122 000011C0 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3123 000011C2 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3124 000011C5 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3125 000011C7 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3126 000011CB E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3127                              <1> K42A:
  3128                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3129 000011D0 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3130                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3131                              <1> 	;;jb	K56 ; 20/02/2015
  3132                              <1> 	;;jmp	K64 ; 20/02/2015
  3133                              <1> K42B:
  3134 000011D2 BB[A8650000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3135                              <1> 	;;jmp	K64
  3136                              <1> 	;jb	K56 ;; 20/02/2015	
  3137                              <1> 	; 24/12/2021
  3138 000011D7 7267                <1> 	jb	short K45F
  3139 000011D9 E9B9000000          <1> 	jmp	K64	
  3140                              <1>         ;
  3141                              <1> 	;-----	NOT IN CONTROL SHIFT
  3142                              <1> K44:					; NOT-CTL-SHIFT
  3143 000011DE 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3144 000011E0 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3145 000011E2 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3146 000011E5 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3147 000011E7 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3148 000011EA 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3149 000011EC EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3150                              <1> K44A:
  3151 000011EE F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3152 000011F1 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3153                              <1> 	;
  3154                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3155                              <1> K44B:
  3156 000011F3 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3157 000011F5 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3158 000011FA B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3159 000011FC E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3160                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3161                              <1> 	;PUSH 	BP			; SAVE POINTER
  3162                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3163                              <1> 	;POP	BP			; RESTORE POINTER
  3164 000011FE 8025[B6660000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3165 00001205 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3166                              <1> 	;
  3167                              <1> 	;-----	HANDLE IN-CORE KEYS
  3168                              <1> K45:					; NOT-PRINT-SCREEN
  3169 0000120A 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3170 0000120C 7734                <1> 	ja	short K46		; JUMP IF NOT
  3171 0000120E 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3172 00001210 7505                <1> 	jne	short K45A		; NO, JUMP
  3173 00001212 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3174 00001215 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3175                              <1> K45A:
  3176 00001217 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3177 0000121C BF[7E650000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3178 00001221 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3179                              <1> 		; 20/02/2015
  3180 00001223 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3181                              <1> 	;
  3182 00001225 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3183 00001228 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3184                              <1> K45B:
  3185 0000122A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3186 0000122D 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3187                              <1> 					; NO, LOWERCASE
  3188                              <1> K45C:
  3189 0000122F BB[00660000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3190 00001234 EB51                <1> 	jmp	short K56	
  3191                              <1> K45D:					; ALMOST-CAPS-STATE
  3192 00001236 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3193 00001239 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3194                              <1> K45E:
  3195 0000123B BB[58660000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3196 00001240 EB45                <1> K45F:	jmp	short K56
  3197                              <1> 	;
  3198                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3199                              <1> K46:					; NOT IN-CORE AREA
  3200 00001242 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3201                              <1> 	;ja	short K47		; JUMP IF NOT
  3202                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3203 00001244 7635                <1> 	jna	short K53		
  3204                              <1> 	;
  3205                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3206                              <1> K47:					; NOT F1 - F10
  3207 00001246 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3208 00001248 772D                <1> 	ja	short K52		; JUMP IF NOT
  3209                              <1> 	;
  3210                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3211                              <1> K48:
  3212 0000124A 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3213 0000124C 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3214 0000124E 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3215 00001250 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3216 00001252 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3217 00001255 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3218                              <1> 	;		
  3219 00001257 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3220 0000125A 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3221 0000125C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3222                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3223 0000125F 75DA                <1> 	jnz	short K45E
  3224                              <1> 	;
  3225                              <1> 	;-----	BASE CASE FOR KEYPAD
  3226                              <1> K49:					
  3227 00001261 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3228 00001263 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3229 00001265 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3230 00001267 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3231                              <1> K49A:
  3232 00001269 BB[00660000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3233 0000126E EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3234                              <1> 	;
  3235                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3236                              <1> K50:					; ALMOST-NUM-STATE
  3237 00001270 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3238 00001273 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3239 00001275 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3240                              <1> 	;
  3241                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3242                              <1> K52:					; NOT A NUMPAD KEY
  3243 00001277 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3244                              <1> 	;jne	short K53		; JUMP IF NOT
  3245                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3246 00001279 74AF                <1> 	je	short K45B		
  3247                              <1> 	;
  3248                              <1> 	;-----	MUST BE F11 OR F12 
  3249                              <1> K53:					; F1 - F10 COME HERE, TOO
  3250 0000127B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3251 0000127E 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3252                              <1> 		; 20/02/2015 
  3253 00001280 BB[58660000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3254 00001285 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3255                              <1> 	;
  3256                              <1> 	;-----	TRANSLATE THE CHARACTER
  3257                              <1> K56:					; TRANSLATE-CHAR
  3258 00001287 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3259 00001289 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3260 0000128A F605[B6660000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3261 00001291 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3262 00001293 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3263 00001295 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3264                              <1> 	;
  3265                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3266                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3267 00001297 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3268 00001299 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3269 0000129A 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3270 0000129C B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3271 0000129E F605[B6660000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3272 000012A5 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3273 000012A7 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3274                              <1> 	;
  3275                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3276                              <1> K57:					; BUFFER_FILL
  3277 000012A9 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3278 000012AB 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3279                              <1> 	; 24/12/2021
  3280                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3281 000012AD 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3282                              <1> 	; 24/12/2021
  3283 000012B0 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3284                              <1> 	;je	K26			; INTERRUPT_RETURN
  3285                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3286 000012B2 E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3287                              <1> K61:					; NOT-CAPS-STATE
  3288 000012B7 8B1D[C4660000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3289 000012BD 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3290 000012BF E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3291 000012C4 3B1D[C0660000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3292 000012CA 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3293 000012CC 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3294 000012CF 891D[C4660000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3295 000012D5 E949FDFFFF          <1> 	jmp	K26
  3296                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3297                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3298                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3299                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3300                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3301                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3302                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3303                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3304                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3305                              <1> 	;;jmp   K27                    
  3306                              <1> 	;
  3307                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3308                              <1> K62:
  3309 000012DA B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3310 000012DC E620                <1> 	out	INTA00, al
  3311 000012DE 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3312 000012E2 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3313 000012E4 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3314 000012E9 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3315                              <1> 
  3316                              <1> SHIP_IT:
  3317                              <1> 	;---------------------------------------------------------------------------------
  3318                              <1> 	; SHIP_IT
  3319                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3320                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3321                              <1> 	;---------------------------------------------------------------------------------
  3322                              <1> 	;
  3323                              <1> 	;push	ax			; SAVE DATA TO SEND
  3324                              <1> 	; 24/12/2021
  3325 000012EE 50                  <1> 	push	eax
  3326                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3327 000012EF FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3328                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3329 000012F0 B900000100          <1> 	mov	ecx, 10000h			
  3330                              <1> S10:
  3331 000012F5 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3332 000012F7 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3333 000012F9 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3334                              <1> 
  3335                              <1> 	;pop	ax			; GET DATA TO SEND
  3336                              <1> 	; 24/12/2021
  3337 000012FB 58                  <1> 	pop	eax
  3338 000012FC E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3339 000012FE FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3340 000012FF C3                  <1> 	retn				; RETURN TO CALLER
  3341                              <1> 
  3342                              <1> SND_DATA:
  3343                              <1> 	; ---------------------------------------------------------------------------------
  3344                              <1> 	; SND_DATA
  3345                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3346                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3347                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3348                              <1> 	; ---------------------------------------------------------------------------------
  3349                              <1> 	;
  3350                              <1> 	;push	ax			; SAVE REGISTERS
  3351                              <1> 	;push	bx
  3352                              <1> 	; 24/12/2021
  3353 00001300 50                  <1> 	push	eax
  3354 00001301 53                  <1> 	push	ebx
  3355 00001302 51                  <1> 	push	ecx
  3356 00001303 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3357 00001305 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3358                              <1> SD0:
  3359 00001307 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3360 00001308 8025[B5660000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3361                              <1> 	;
  3362                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3363 0000130F B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3364                              <1> SD5:
  3365 00001314 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3366 00001316 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3367 00001318 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3368                              <1> 	;
  3369 0000131A 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3370 0000131C E660                <1> 	out	PORT_A, al		; SEND BYTE
  3371 0000131E FB                  <1> 	sti				; ENABLE INTERRUPTS
  3372                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3373 0000131F B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3374                              <1> SD1:
  3375 00001324 F605[B5660000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3376 0000132B 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3377 0000132D E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3378                              <1> SD2:
  3379 0000132F FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3380 00001331 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3381 00001333 800D[B5660000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3382 0000133A EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3383                              <1> SD3:
  3384 0000133C F605[B5660000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3385 00001343 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3386                              <1> SD4:	
  3387 00001345 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3388                              <1> 	;pop	bx
  3389                              <1> 	;pop	ax
  3390                              <1> 	; 24/12/2021
  3391 00001346 5B                  <1> 	pop	ebx
  3392 00001347 58                  <1> 	pop	eax
  3393 00001348 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3394                              <1> 
  3395                              <1> SND_LED:
  3396                              <1> 	; ---------------------------------------------------------------------------------
  3397                              <1> 	; SND_LED
  3398                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3399                              <1> 	;
  3400                              <1> 	;----------------------------------------------------------------------------------
  3401                              <1> 	;
  3402 00001349 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3403 0000134A F605[B5660000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3404 00001351 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3405                              <1> 	;
  3406 00001353 800D[B5660000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3407 0000135A B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3408 0000135C E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3409 0000135E EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3410                              <1> SND_LED1:
  3411 00001360 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3412 00001361 F605[B5660000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3413 00001368 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3414                              <1> 	;
  3415 0000136A 800D[B5660000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3416                              <1> SL0:
  3417 00001371 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3418 00001373 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3419 00001378 FA                  <1> 	cli
  3420 00001379 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3421 0000137E 8025[B5660000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3422 00001385 0805[B5660000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3423 0000138B F605[B5660000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3424 00001392 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3425                              <1> 	;
  3426 00001394 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3427 00001399 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3428 0000139A F605[B5660000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3429 000013A1 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3430                              <1> SL2:
  3431 000013A3 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3432 000013A5 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3433 000013AA FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3434                              <1> SL3:
  3435 000013AB 8025[B5660000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3436                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3437 000013B2 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3438 000013B3 C3                  <1> 	retn				; RETURN TO CALLER
  3439                              <1> 
  3440                              <1> MAKE_LED:
  3441                              <1> 	;---------------------------------------------------------------------------------
  3442                              <1> 	; MAKE_LED
  3443                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3444                              <1> 	;	THE MODE INDICATORS.
  3445                              <1> 	;---------------------------------------------------------------------------------
  3446                              <1> 	;
  3447                              <1> 	;push 	cx			; SAVE CX
  3448 000013B4 A0[B3660000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3449 000013B9 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3450                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3451                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3452 000013BB C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3453 000013BE 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3454                              <1> 	;pop	cx
  3455 000013C0 C3                  <1> 	retn				; RETURN TO CALLER
  3456                              <1> 
  3457                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3458                              <1> 
  3459                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1880                                  
  1881                                  %include 'video.inc' ; 07/03/2015
  1882                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - VIDEO.INC
  1883                              <1> ; Last Modification: 14/06/2022
  1884                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1885                              <1> ;
  1886                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1887                              <1> 
  1888                              <1> ; 14/06/2022
  1889                              <1> ; 26/02/2022
  1890                              <1> ; 07/02/2022
  1891                              <1> ; 02/02/2022 (simplified scroll up)
  1892                              <1> ; 16/01/2016
  1893                              <1> ; 30/06/2015
  1894                              <1> ; 27/06/2015
  1895                              <1> ; 11/03/2015
  1896                              <1> ; 02/09/2014
  1897                              <1> ; 30/08/2014
  1898                              <1> ; VIDEO FUNCTIONS
  1899                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1900                              <1> 
  1901                              <1> write_tty:
  1902                              <1> 	; 02/02/2022
  1903                              <1> 	; 13/08/2015
  1904                              <1> 	; 02/09/2014
  1905                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1906                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1907                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1908                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1909                              <1> 	;
  1910                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1911                              <1> 	;	   AL = Character to be written
  1912                              <1> 	;	   EBX = Video Page (0 to 7)
  1913                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1914                              <1> 
  1915                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1916                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1917                              <1> 
  1918                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1919                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1920                              <1> ;
  1921                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1922                              <1> ;
  1923                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1924                              <1> ;										:
  1925                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1926                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1927                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1928                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1929                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1930                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1931                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1932                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1933                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1934                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1935                              <1> ;   THE 0 COLOR IS USED.							:
  1936                              <1> ;   ENTRY --									:
  1937                              <1> ;     (AH) = CURRENT CRT MODE							:
  1938                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1939                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1940                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1941                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1942                              <1> ;   EXIT -- 									:
  1943                              <1> ;     ALL REGISTERS SAVED							:
  1944                              <1> ;--------------------------------------------------------------------------------
  1945                              <1> 
  1946 000013C1 FA                  <1> 	cli
  1947                              <1> 	;
  1948                              <1> 	; READ CURSOR (04/12/2013)
  1949                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1950 000013C2 08FF                <1> 	or	bh, bh
  1951                              <1> 	;jnz	beeper
  1952                              <1> 	; 02/02/2022
  1953 000013C4 7405                <1> 	jz	short u14
  1954 000013C6 E992000000          <1> 	jmp	beeper
  1955                              <1> u14:
  1956                              <1> 	; 02/02/2022
  1957                              <1> 	;; 01/09/2014
  1958                              <1> 	;cmp	byte [CRT_MODE], 3
  1959                              <1> 	;je	short m3
  1960                              <1> 	;;
  1961                              <1> 	;call	set_mode
  1962                              <1> m3:
  1963 000013CB 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1964                              <1> 	;shl	si, 1
  1965                              <1> 	; 02/02/2022
  1966 000013CD D1E6                <1> 	shl	esi, 1
  1967 000013CF 81C6[A66C0000]      <1> 	add	esi, cursor_posn
  1968 000013D5 668B16              <1> 	mov	dx, [esi]
  1969                              <1> 	;
  1970                              <1> 	; dx now has the current cursor position
  1971                              <1> 	;
  1972 000013D8 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1973 000013DA 7647                <1> 	jbe	short u8
  1974                              <1> 	;
  1975                              <1> 	; write the char to the screen
  1976                              <1> u0:	
  1977                              <1> 	; ah = attribute/color
  1978                              <1> 	; al = character
  1979                              <1> 	; bl = video page number (0 to 7)
  1980                              <1> 	; bh = 0
  1981                              <1> 	;
  1982 000013DC E8D2010000          <1> 	call	write_c_current
  1983                              <1> 	;
  1984                              <1> 	; position the cursor for next char
  1985 000013E1 FEC2                <1> 	inc	dl		; next column
  1986                              <1> 	;cmp	dl, [CRT_COLS]
  1987 000013E3 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1988                              <1>         ;jne	set_cpos
  1989                              <1> 	; 02/02/2022
  1990 000013E6 7405                <1> 	je	short u13
  1991 000013E8 E9DE000000          <1> 	jmp	set_cpos
  1992                              <1> u13:
  1993 000013ED B200                <1> 	mov	dl, 0		; column = 0
  1994                              <1> u10:				; (line feed found)
  1995 000013EF 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1996 000013F2 7228                <1> 	jb 	short u6
  1997                              <1> 	;
  1998                              <1> 	; scroll required
  1999                              <1> u1:	
  2000                              <1> 	; SET CURSOR POSITION (04/12/2013)
  2001 000013F4 E8D2000000          <1> 	call	set_cpos
  2002                              <1> 	;
  2003                              <1> 	; determine value to fill with during scroll
  2004                              <1> u2:
  2005                              <1> 	; READ_AC_CURRENT		:
  2006                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  2007                              <1> 	;    AT THE CURRENT CURSOR POSITION
  2008                              <1> 	;
  2009                              <1> 	; INPUT				
  2010                              <1> 	;	(AH) = CURRENT CRT MODE
  2011                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2012                              <1> 	;	(DS) = DATA SEGMENT
  2013                              <1> 	;	(ES) = REGEN SEGMENT
  2014                              <1> 	; OUTPUT			
  2015                              <1> 	;	(AL) = CHARACTER READ
  2016                              <1> 	;	(AH) = ATTRIBUTE READ
  2017                              <1> 	;
  2018                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2019                              <1> 	;
  2020                              <1> 	; bl = video page number
  2021                              <1> 	;
  2022 000013F9 E829010000          <1> 	call	find_position	; get regen location and port address
  2023                              <1> 	; dx = status port
  2024                              <1> 	; esi = cursor location/address
  2025                              <1> p11:
  2026 000013FE FB                  <1> 	sti			; enable interrupts
  2027 000013FF 90                  <1> 	nop			; allow for small interupts window
  2028 00001400 FA                  <1> 	cli			; blocks interrupts for single loop
  2029 00001401 EC                  <1> 	in	al, dx		; get status from adapter
  2030 00001402 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2031 00001404 75F8                <1> 	jnz	short p11	; wait until it is
  2032                              <1> p12:				; now wait for either retrace high
  2033 00001406 EC                  <1> 	in	al, dx		; get status
  2034 00001407 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2035 00001409 74FB                <1> 	jz	short p12	; wait until either is active	
  2036                              <1> p13:
  2037 0000140B 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2038 00001411 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2039                              <1> 	;
  2040                              <1> 	; al = character, ah = attribute
  2041                              <1> 	;
  2042 00001414 FB                  <1> 	sti
  2043                              <1> 	; bl = video page number 	
  2044                              <1> u3:
  2045                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2046                              <1> 	;;sub	cx, cx		; upper left corner
  2047                              <1> 	;;mov	dh, 25-1 	; lower right row
  2048                              <1> 	;;;mov	dl, [CRT_COLS]
  2049                              <1> 	;mov	dl, 80		; lower right column	
  2050                              <1> 	;;dec	dl
  2051                              <1> 	;;mov	dl, 79
  2052                              <1> 
  2053                              <1> 	;;call	scroll_up	; 04/12/2013
  2054                              <1> 	;;; 11/03/2015
  2055                              <1> 	; 02/09/2014
  2056                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2057                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2058                              <1> 	; 11/03/2015
  2059                              <1> 	;sub	cx, cx
  2060                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2061                              <1> 	;
  2062                              <1> 	; 02/02/2022 (simplied scroll up)
  2063                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2064                              <1> 	;
  2065 00001415 B001                <1> 	mov	al, 1		; scroll 1 line up
  2066                              <1> 		; ah = attribute
  2067 00001417 E935010000          <1> 	jmp	scroll_up
  2068                              <1> ;u4:
  2069                              <1> 	;;int	10h		; video-call return
  2070                              <1> 				; scroll up the screen
  2071                              <1> 				; tty return
  2072                              <1> ;u5:
  2073                              <1> 	;retn			; return to the caller
  2074                              <1> 
  2075                              <1> u6:				; set-cursor-inc
  2076 0000141C FEC6                <1> 	inc	dh		; next row
  2077                              <1> 				; set cursor
  2078                              <1> ;u7:					
  2079                              <1> 	;;mov	ah, 02h
  2080                              <1> 	;;jmp	short u4 	; establish the new cursor
  2081                              <1> 	;call	set_cpos
  2082                              <1> 	;jmp 	short u5
  2083 0000141E E9A8000000          <1> 	jmp     set_cpos
  2084                              <1> 
  2085                              <1> 	; check for control characters
  2086                              <1> u8:
  2087 00001423 7434                <1> 	je	short u9
  2088 00001425 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2089 00001427 74C6                <1> 	je	short u10
  2090 00001429 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2091 0000142B 7430                <1> 	je	short u11
  2092 0000142D 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2093                              <1> 	;jne	short u0
  2094 0000142F 7420                <1> 	je	short bs	; 12/12/2013
  2095                              <1> 	; 12/12/2013 (tab stop)
  2096 00001431 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2097 00001433 75A7                <1> 	jne	short u0
  2098 00001435 88D0                <1> 	mov	al, dl
  2099 00001437 6698                <1> 	cbw
  2100 00001439 B108                <1> 	mov	cl, 8
  2101 0000143B F6F1                <1> 	div	cl
  2102 0000143D 28E1                <1> 	sub	cl, ah
  2103                              <1> ts:
  2104                              <1> 	; 02/09/2014
  2105                              <1> 	; 01/09/2014
  2106 0000143F B020                <1> 	mov	al, 20h
  2107                              <1> tsloop:
  2108                              <1> 	;push	cx
  2109                              <1> 	;push	ax
  2110                              <1> 	; 02/02/2022
  2111 00001441 51                  <1> 	push	ecx
  2112 00001442 50                  <1> 	push	eax
  2113 00001443 30FF                <1> 	xor 	bh, bh
  2114                              <1> 	;mov	bl, [active_page]
  2115 00001445 E881FFFFFF          <1> 	call	m3
  2116                              <1> 	; 02/02/2022
  2117 0000144A 58                  <1> 	pop	eax
  2118 0000144B 59                  <1>  	pop	ecx
  2119                              <1> 	;pop	ax  ; ah = attribute/color
  2120                              <1> 	;pop	cx
  2121 0000144C FEC9                <1> 	dec	cl
  2122 0000144E 75F1                <1> 	jnz	short tsloop
  2123 00001450 C3                  <1> 	retn
  2124                              <1> bs:	
  2125                              <1> 	; back space found
  2126 00001451 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2127                              <1> 	;je	short u7 	; set_cursor
  2128 00001453 7476                <1> 	jz	short set_cpos
  2129                              <1> 	;dec	dx     		; no -- just move it back
  2130                              <1> 	; 02/02/2022
  2131 00001455 FECA                <1> 	dec	dl
  2132                              <1> 	;jmp	short u7
  2133 00001457 EB72                <1> 	jmp	short set_cpos
  2134                              <1> 
  2135                              <1> 	; carriage return found
  2136                              <1> u9:
  2137 00001459 B200                <1> 	mov	dl, 0 		; move to first column
  2138                              <1> 	;jmp	short u7
  2139 0000145B EB6E                <1> 	jmp	short set_cpos
  2140                              <1> 
  2141                              <1> 	; line feed found
  2142                              <1> ;u10:
  2143                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2144                              <1> ;	jne	short u6 	; no, just set the cursor
  2145                              <1> ;       jmp     u1              ; yes, scroll the screen
  2146                              <1> 
  2147                              <1> beeper: 
  2148                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2149                              <1> 	; 18/01/2014
  2150                              <1> 	; 03/12/2013
  2151                              <1> 	; bell found
  2152                              <1> u11:
  2153 0000145D FB                  <1> 	sti
  2154 0000145E 3A1D[B66C0000]      <1> 	cmp	bl, [active_page]
  2155 00001464 7551                <1> 	jne	short u12	; Do not sound the beep 
  2156                              <1> 				; if it is not written on the active page
  2157 00001466 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2158 0000146A B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2159                              <1> 	;call	beep		; sound the pod bell
  2160                              <1> 	;jmp	short u5 	; tty_return
  2161                              <1> 	;retn
  2162                              <1> 	
  2163                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2164                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2165                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2166                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2167                              <1> 
  2168                              <1> beep:
  2169                              <1> 	; 07/02/2015
  2170                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2171                              <1> 	; 18/01/2014
  2172                              <1> 	; 03/12/2013
  2173                              <1> 	;
  2174                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2175                              <1> 	;
  2176                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2177                              <1> 	;
  2178                              <1> 	; ENTRY:
  2179                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2180                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2181                              <1> 	; EXIT:			:
  2182                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2183                              <1> 
  2184 0000146C 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2185 0000146D FA                  <1> 	cli			; block interrupts during update
  2186 0000146E B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2187 00001470 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2188 00001472 EB00                <1> 	jmp	$+2		; I/O delay
  2189 00001474 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2190 00001476 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2191 00001478 EB00                <1> 	jmp	$+2		; I/O delay
  2192 0000147A 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2193 0000147C E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2194 0000147E E461                <1> 	in	al, PORT_B	; get current setting of port
  2195 00001480 88C4                <1> 	mov	ah, al		; save that setting
  2196 00001482 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2197 00001484 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2198                              <1> 	;popf	; 18/01/2014
  2199 00001486 FB                  <1> 	sti
  2200                              <1> g7:				; 1/64 second per count (bl)
  2201 00001487 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2202 0000148C E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2203 00001491 FECB                <1> 	dec	bl		; (bl) length count expired?
  2204 00001493 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2205                              <1> 	;
  2206                              <1> 	;pushf			; save interrupt status
  2207 00001495 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2208 00001496 E461                <1> 	in	al, PORT_B	; get current port value
  2209                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2210 00001498 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2211 0000149A 20C4                <1>         and	ah, al		; someone turned them off during beep
  2212 0000149C 88E0                <1> 	mov	al, ah		; recover value of port
  2213                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2214 0000149E 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2215 000014A0 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2216                              <1> 	;popf			; restore interrupt flag state
  2217 000014A2 FB                  <1> 	sti
  2218 000014A3 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2219 000014A8 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2220                              <1> 	;pushf			; save interrupt status
  2221 000014AD FA                  <1> 	cli			; block interrupts during update
  2222 000014AE E461                <1> 	in	al, PORT_B	; get current port value in case	
  2223 000014B0 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2224 000014B2 08E0                <1> 	or	al, ah		; recover value of port_b
  2225 000014B4 E661                <1> 	out	PORT_B, al	; restore speaker status
  2226 000014B6 9D                  <1> 	popf			; restore interrupt flag state
  2227                              <1> u12:	
  2228 000014B7 C3                  <1> 	retn
  2229                              <1> 
  2230                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2231                              <1> 
  2232                              <1> WAITF:
  2233                              <1> waitf:
  2234                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2235                              <1> 	; 03/12/2013
  2236                              <1> 	;
  2237                              <1> ;	push	ax		; save work register (ah)	
  2238                              <1> ;waitf1:
  2239                              <1> 				; use timer 1 output bits
  2240                              <1> ;	in	al, PORT_B	; read current counter output status
  2241                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2242                              <1> ;	cmp	al, ah		; did it just change
  2243                              <1> ;	je	short waitf1	; wait for a change in output line
  2244                              <1> ;	;
  2245                              <1> ;	mov	ah, al		; save new lflag state
  2246                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2247                              <1> ;	;
  2248                              <1> ;	pop	ax		; restore (ah)
  2249                              <1> ;	retn			; return (cx)=0
  2250                              <1> 
  2251                              <1> ; 02/02/2022
  2252                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2253                              <1> ; 17/12/2014 (dsectrm2.s)
  2254                              <1> ; WAITF
  2255                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2256                              <1> ;
  2257                              <1> ;---WAITF-----------------------------------------------------------------------
  2258                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2259                              <1> ; ENTRY:
  2260                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2261                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2262                              <1> ; EXIT:
  2263                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2264                              <1> ;	(CX) = 0	
  2265                              <1> ;-------------------------------------------------------------------------------
  2266                              <1> 
  2267                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2268                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2269                              <1> 
  2270                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2271 000014B8 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2272                              <1> 	;push	ax
  2273                              <1> 	; 16/12/2014
  2274                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2275 000014B9 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2276                              <1> ;17/12/2014	
  2277                              <1> ;WAITF1:
  2278                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2279                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2280                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2281                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2282                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2283                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2284                              <1> 	;
  2285                              <1> 	; 17/12/2014
  2286                              <1> 	;
  2287                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2288                              <1> 	;
  2289                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2290                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2291                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2292                              <1> WR_STATE_0:
  2293 000014BB E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2294 000014BD A810                <1> 	TEST	AL,010H
  2295 000014BF 74FA                <1> 	JZ	SHORT WR_STATE_0
  2296                              <1> WR_STATE_1:
  2297 000014C1 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2298 000014C3 A810                <1> 	TEST	AL,010H
  2299 000014C5 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2300 000014C7 E2F2                <1>         LOOP    WR_STATE_0
  2301                              <1> 	;
  2302                              <1> 	;pop	ax
  2303 000014C9 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2304 000014CA C3                  <1> 	RETn				; (CX) = 0
  2305                              <1> 
  2306                              <1> set_cpos:
  2307                              <1> 	; 14/06/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.4)
  2308                              <1> 	; 26/02/2022
  2309                              <1> 	; 02/02/2022
  2310                              <1> 	; 27/06/2015
  2311                              <1> 	; 01/09/2014
  2312                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2313                              <1> 	;
  2314                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2315                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2316                              <1> 	;
  2317                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2318                              <1> 	;
  2319                              <1> 	; SET_CPOS
  2320                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2321                              <1> 	;	NEW X-Y VALUES PASSED
  2322                              <1> 	; INPUT
  2323                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2324                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2325                              <1> 	; OUTPUT
  2326                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2327                              <1> 	;
  2328 000014CB 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2329 000014CE D0E0                <1>         shl     al, 1   ; word offset
  2330 000014D0 BE[A66C0000]        <1> 	mov	esi, cursor_posn
  2331 000014D5 01C6                <1>         add     esi, eax
  2332 000014D7 668916              <1> 	mov	[esi], dx ; save the pointer
  2333 000014DA 381D[B66C0000]      <1> 	cmp	[active_page], bl
  2334 000014E0 7531                <1> 	jne	short m17
  2335                              <1> 
  2336                              <1> 	; 14/06/2022
  2337                              <1> 	;cli ; 26/02/2022
  2338                              <1> 
  2339                              <1> 	;call	m18	;h CURSOR SET
  2340                              <1> ;m17:			; SET_CPOS_RETURN
  2341                              <1> 	; 01/09/2014
  2342                              <1> 	;retn
  2343                              <1> 		; DX = row/column
  2344                              <1> m18:
  2345 000014E2 E832000000          <1> 	call	position ; determine location in regen buffer	
  2346                              <1> 	;mov	cx, [CRT_START]
  2347                              <1> 	; 26/02/2022
  2348 000014E7 0FB70D[A46C0000]    <1> 	movzx	ecx, word [CRT_START]
  2349 000014EE 01C1                <1> 	add	ecx, eax
  2350                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2351                              <1> 			; to the start address (offset) for this page
  2352                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2353                              <1> 	; 26/02/2022
  2354 000014F0 D1E9                <1> 	shr	ecx, 1
  2355 000014F2 B40E                <1> 	mov	ah, 14	; register number for cursor
  2356                              <1> 	
  2357                              <1> 	; 14/06/2022
  2358                              <1> 	;call	m16	; output value to the 6845
  2359                              <1> 	;sti	; 26/02/2022
  2360                              <1> 	;retn
  2361                              <1> 
  2362                              <1> 	; 14/06/2022
  2363                              <1> 	; 26/02/2022
  2364                              <1> 	; 02/02/2022
  2365                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2366                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2367                              <1> m16:
  2368                              <1> 	; 14/06/2022
  2369 000014F4 FA                  <1> 	cli	; 26/02/2022
  2370                              <1> 	;mov	dx, [addr_6845] ; address register
  2371 000014F5 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2372 000014F9 88E0                <1> 	mov	al, ah	; get value
  2373 000014FB EE                  <1> 	out	dx, al	; register set
  2374                              <1> 	;inc	dx	; data register
  2375                              <1> 	; 02/02/2022
  2376 000014FC FEC2                <1> 	inc	dl
  2377 000014FE EB00                <1> 	jmp	$+2	; i/o delay
  2378 00001500 88E8                <1> 	mov	al, ch	; data
  2379 00001502 EE                  <1> 	out	dx, al	
  2380                              <1> 	;dec	dx
  2381                              <1> 	; 02/02/2022	
  2382 00001503 FECA                <1> 	dec	dl
  2383 00001505 88E0                <1> 	mov	al, ah
  2384 00001507 FEC0                <1> 	inc	al	; point to other data register
  2385 00001509 EE                  <1> 	out	dx, al	; set for second register
  2386                              <1> 	;inc	dx
  2387                              <1> 	; 02/02/2022
  2388 0000150A FEC2                <1> 	inc	dl
  2389 0000150C EB00                <1> 	jmp	$+2	; i/o delay
  2390 0000150E 88C8                <1> 	mov	al, cl	; second data value
  2391 00001510 EE                  <1> 	out	dx, al
  2392                              <1> 	; 14/06/2022
  2393 00001511 FB                  <1> 	sti	; 26/02/2022
  2394                              <1> ;m17:
  2395 00001512 C3                  <1> 	retn
  2396                              <1> m17:
  2397                              <1> 	; 14/06/2022
  2398                              <1> 	; ('write_tty' must not return to 'putc'/'wtty' with cf)
  2399 00001513 F8                  <1> 	clc
  2400 00001514 C3                  <1> 	retn
  2401                              <1> 
  2402                              <1> set_ctype:
  2403                              <1> 	; 07/02/2022
  2404                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2405                              <1> 	;
  2406                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2407                              <1> 
  2408                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2409                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2410                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2411                              <1> ;          OR NO CURSOR AT ALL
  2412                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2413                              <1> 
  2414                              <1> ;------------------------------------------------
  2415                              <1> ; SET_CTYPE
  2416                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2417                              <1> ; INPUT
  2418                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2419                              <1> ; OUTPUT	
  2420                              <1> ;	NONE
  2421                              <1> ;------------------------------------------------
  2422                              <1> 
  2423 00001515 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2424                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2425                              <1> 	;call	m16	; output cx register
  2426                              <1> 	;retn
  2427                              <1> 	; 07/02/2022
  2428 00001517 EBDB                <1> 	jmp	short m16
  2429                              <1> 
  2430                              <1> position:
  2431                              <1> 	; 26/02/2022
  2432                              <1> 	; 02/02/2022
  2433                              <1> 	; 27/06/2015
  2434                              <1> 	; 02/09/2014
  2435                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2436                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2437                              <1> 	;
  2438                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2439                              <1> 	;
  2440                              <1> 	; POSITION
  2441                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2442                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2443                              <1> 	; INPUT
  2444                              <1> 	;	AX = ROW, COLUMN POSITION
  2445                              <1> 	; OUTPUT
  2446                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2447                              <1> 
  2448                              <1> 		; DX = ROW, COLUMN POSITION
  2449                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2450 00001519 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2451 0000151B B050                <1> 	mov	al, 80	; determine bytes to row	
  2452 0000151D F6E6                <1> 	mul	dh	; row value
  2453                              <1> 	;xor	dh, dh	; 0
  2454                              <1> 	;add	ax, dx	; add column value to the result
  2455                              <1> 	; 26/02/2022
  2456 0000151F 00D0                <1> 	add	al, dl
  2457 00001521 80D400              <1> 	adc	ah, 0	
  2458                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2459                              <1> 	; 02/02/2022
  2460 00001524 D1E0                <1> 	shl	eax, 1
  2461                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2462 00001526 C3                  <1> 	retn
  2463                              <1> 
  2464                              <1> find_position:
  2465                              <1> 	; 02/02/2022
  2466                              <1> 	; 27/06/2015
  2467                              <1> 	; 07/09/2014
  2468                              <1> 	; 02/09/2014
  2469                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2470                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2471 00001527 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2472 0000152A 89CE                <1> 	mov	esi, ecx
  2473                              <1> 	;shl	si, 1
  2474                              <1> 	; 02/02/2022
  2475 0000152C D1E6                <1> 	shl	esi, 1
  2476 0000152E 668B96[A66C0000]    <1> 	mov	dx, [esi+cursor_posn]
  2477 00001535 7409                <1> 	jz	short p21
  2478                              <1> 	;xor	si, si
  2479                              <1> 	; 02/02/2022
  2480 00001537 31F6                <1> 	xor	esi, esi
  2481                              <1> p20:
  2482                              <1> 	;add	si, [CRT_LEN]
  2483 00001539 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2484 0000153E E2F9                <1> 	loop	p20
  2485                              <1> p21:
  2486 00001540 6621D2              <1> 	and	dx, dx
  2487 00001543 7407                <1> 	jz	short p22
  2488 00001545 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2489 0000154A 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2490                              <1> p22:	
  2491                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2492                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2493                              <1> 	;add	dx, 6	; point at status port
  2494 0000154C 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2495                              <1> 	; cx = 0
  2496 00001550 C3                  <1> 	retn
  2497                              <1> 
  2498                              <1> scroll_up:
  2499                              <1> 	; 02/02/2022 (simplified scroll up)
  2500                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2501                              <1> 	; 16/01/2016
  2502                              <1> 	; 07/09/2014
  2503                              <1> 	; 02/09/2014
  2504                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2505                              <1> 	; 04/04/2014
  2506                              <1> 	; 04/12/2013
  2507                              <1> 	;
  2508                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2509                              <1> 	;
  2510                              <1> 	; SCROLL UP
  2511                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2512                              <1> 	;	ON THE SCREEN
  2513                              <1> 	; INPUT
  2514                              <1> 	;	(AH) = CURRENT CRT MODE
  2515                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2516                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2517                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2518                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2519                              <1> 	;	(DS) = DATA SEGMENT
  2520                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2521                              <1> 	; OUTPUT
  2522                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2523                              <1> 	;
  2524                              <1> 	;	bh = 0  (02/09/2014)
  2525                              <1> 	;
  2526                              <1> 	; ((ah = 3))
  2527                              <1> 	; cl = left upper column
  2528                              <1> 	; ch = left upper row
  2529                              <1> 	; dl = right lower column
  2530                              <1> 	; dh = right lower row
  2531                              <1> 	;
  2532                              <1> 	; al = line count 
  2533                              <1> 	; ah = attribute to be used on blanked line
  2534                              <1> 	; bl = video page number (0 to 7)
  2535                              <1> 	; 
  2536                              <1> 
  2537                              <1> 	; 02/02/2022 'scroll_up' code
  2538                              <1> 	; ------------------------------------------------------
  2539                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2540                              <1> 
  2541                              <1> 	; INPUT:
  2542                              <1> 	;		
  2543                              <1> 	; al = line count 
  2544                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2545                              <1> 	; ah = attribute to be used on blanked line
  2546                              <1> 	; bl = video page number (0 to 7)
  2547                              <1> 
  2548                              <1> 	;cli
  2549 00001551 31C9                <1> 	xor	ecx, ecx
  2550 00001553 88C1                <1> 	mov	cl, al ; line count (cl)
  2551 00001555 BE00800B00          <1> 	mov	esi, 0B8000h
  2552 0000155A 3A1D[B66C0000]      <1> 	cmp	bl, [active_page]
  2553 00001560 7411                <1> 	je	short n1
  2554 00001562 20DB                <1> 	and	bl, bl
  2555 00001564 7422                <1> 	jz	short n3
  2556 00001566 88DD                <1> 	mov	ch, bl ; video page number
  2557                              <1> n0:
  2558 00001568 6681C6A00F          <1> 	add	si, 25*80*2
  2559 0000156D FECD                <1> 	dec	ch
  2560 0000156F 75F7                <1> 	jnz	short n0
  2561 00001571 EB15                <1> 	jmp	short n3
  2562                              <1> n1:
  2563 00001573 660335[A46C0000]    <1> 	add	si, [CRT_START]
  2564                              <1> 	;
  2565 0000157A 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2566                              <1> n2:			 ; wait_display_enable
  2567 0000157E EC                  <1> 	in	al, dx	 ; get port
  2568 0000157F A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2569 00001581 74FB                <1> 	jz	short n2 ; wait_display_enable
  2570 00001583 B025                <1> 	mov	al, 25h
  2571 00001585 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2572 00001587 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2573                              <1> n3:
  2574                              <1> 	; cl = line count
  2575                              <1> 	; ah = attribute/color
  2576 00001588 89F7                <1> 	mov	edi, esi
  2577 0000158A 20C9                <1> 	and	cl, cl
  2578 0000158C 741F                <1> 	jz	short n6
  2579 0000158E 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2580 00001593 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2581 00001597 F366A5              <1> 	rep	movsw
  2582 0000159A B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2583                              <1> n4:
  2584                              <1> 	; ah = character attribute/cocor
  2585 0000159C B020                <1> 	mov	al, 20h ; fill with blanks
  2586 0000159E F366AB              <1> 	rep	stosw
  2587                              <1> 
  2588 000015A1 3A1D[B66C0000]      <1> 	cmp	bl, [active_page]
  2589 000015A7 7503                <1> 	jne	short n5
  2590                              <1> 
  2591                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2592 000015A9 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2593                              <1> 	;mov	dx, 03D8h ; always set color card port
  2594 000015AB EE                  <1> 	out	dx, al
  2595                              <1> n5:
  2596 000015AC C3                  <1> 	retn
  2597                              <1> n6:
  2598                              <1> 	; clear video page
  2599 000015AD 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2600 000015B1 EBE9                <1> 	jmp	short n4
  2601                              <1> 
  2602                              <1> 	; 26/02/2022
  2603                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2604                              <1> 	; ------------------------------------------------------
  2605                              <1> 
  2606                              <1> 	; Test	Line Count
  2607                              <1> 	or	al, al
  2608                              <1> 	jz	short al_set
  2609                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2610                              <1> 	sub	bh, ch
  2611                              <1> 	inc	bh	; adjust difference by 1
  2612                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2613                              <1> 	jne	short al_set ; if not the we're all set
  2614                              <1> 	xor	al, al	; otherwise set al to zero
  2615                              <1> al_set:
  2616                              <1> 	xor	bh, bh	; 0
  2617                              <1> 	;push	ax
  2618                              <1> 	push	eax ; 26/02/2022
  2619                              <1> 	;mov 	esi, [crt_base]
  2620                              <1>         mov     esi, 0B8000h  
  2621                              <1>         cmp     bl, [active_page]
  2622                              <1> 	jne	short n0
  2623                              <1> 	;
  2624                              <1>         mov     ax, [CRT_START]
  2625                              <1>         add     si, ax
  2626                              <1>         jmp     short n1
  2627                              <1> n0:
  2628                              <1>         and     bl, bl
  2629                              <1> 	jz	short n1
  2630                              <1> 	mov	al, bl
  2631                              <1> n0x:
  2632                              <1>         ;add    si, [CRT_LEN]
  2633                              <1>         ;add    esi, 80*25*2 
  2634                              <1>         add     si, 80*25*2
  2635                              <1>         dec	al
  2636                              <1> 	jnz	short n0x
  2637                              <1> n1:	
  2638                              <1>         ; Scroll position
  2639                              <1> 	;push	dx ; 26/02/2022
  2640                              <1> 	mov	dx, cx	; now, upper left position in DX
  2641                              <1> 	call	position
  2642                              <1> 	add	esi, eax
  2643                              <1> 	mov	edi, esi
  2644                              <1> 	;pop	dx	; lower right position in DX
  2645                              <1> 	sub	dx, cx
  2646                              <1> 	inc	dh	; dh = #rows 
  2647                              <1> 	inc	dl	; dl = #cols in block
  2648                              <1> 	;pop	ax	; al = line count, ah = attribute
  2649                              <1> 	pop	eax ; 26/02/2022
  2650                              <1> 	xor	ecx, ecx
  2651                              <1> 	mov	cx, ax
  2652                              <1> 	;mov	ah, [CRT_COLS]
  2653                              <1> 	mov	ah, 80
  2654                              <1> 	mul	ah	; determine offset to from address
  2655                              <1> 	add	ax, ax  ; *2 for attribute byte
  2656                              <1> 	;
  2657                              <1> 	;push	ax	; offset 
  2658                              <1> 	;push	dx
  2659                              <1> 	; 26/02/2022
  2660                              <1> 	push	eax
  2661                              <1> 	push	edx
  2662                              <1> 	;
  2663                              <1> 	; 04/04/2014
  2664                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2665                              <1> n8:                      ; wait_display_enable
  2666                              <1>         in      al, dx   ; get port
  2667                              <1> 	test	al, RVRT ; wait for vertical retrace
  2668                              <1> 	jz	short n8 ; wait_display_enable
  2669                              <1> 	mov	al, 25h
  2670                              <1> 	mov	dl, 0D8h ; address control port
  2671                              <1> 	out	dx, al	; turn off video during vertical retrace
  2672                              <1> 	;pop	dx	; #rows, #cols
  2673                              <1>        	;pop	ax	; offset
  2674                              <1> 	; 26/02/2022
  2675                              <1> 	pop	edx
  2676                              <1> 	pop	eax
  2677                              <1> 	xchg	ax, cx	; 
  2678                              <1> 	; ecx = offset, al = line count, ah = attribute
  2679                              <1> ;n9:
  2680                              <1> 	or	al, al
  2681                              <1>         jz      short n3 
  2682                              <1>         add     esi, ecx ; from address for scroll
  2683                              <1> 	mov	bh, dh  ; #rows in block
  2684                              <1> 	sub	bh, al	; #rows to be moved
  2685                              <1> n2:
  2686                              <1> 	; Move rows
  2687                              <1> 	mov	cl, dl	; get # of cols to move
  2688                              <1> 	push	esi
  2689                              <1> 	push	edi	; save start address
  2690                              <1> n10:
  2691                              <1> 	movsw		; move that line on screen
  2692                              <1> 	dec	cl
  2693                              <1>         jnz     short n10
  2694                              <1> 	pop	edi
  2695                              <1> 	pop	esi	; recover addresses
  2696                              <1>         ;mov    cl, [CRT_COLS] 
  2697                              <1> 	;add	cl, cl
  2698                              <1>         ;mov    ecx, 80*2
  2699                              <1>         mov     cx, 80*2
  2700                              <1>         add     esi, ecx  ; next line
  2701                              <1>         add     edi, ecx
  2702                              <1> 	dec	bh	 ; count of lines to move
  2703                              <1> 	jnz	short n2 ; row loop
  2704                              <1> 	; bh = 0
  2705                              <1> 	mov	dh, al	 ; #rows	
  2706                              <1> n3:
  2707                              <1> 	; attribute in ah
  2708                              <1> 	mov	al, ' '	 ; fill with blanks
  2709                              <1> n3x:
  2710                              <1> 	; Clear rows
  2711                              <1>                 ; dh =  #rows
  2712                              <1>         mov	cl, dl	; get # of cols to clear
  2713                              <1>         push    edi     ; save address
  2714                              <1> n11:
  2715                              <1>         stosw           ; store fill character
  2716                              <1> 	dec	cl
  2717                              <1>         jnz     short n11
  2718                              <1>         pop     edi     ; recover address
  2719                              <1> 	;mov	cl, [CRT_COLS]
  2720                              <1> 	;add	cl, cl
  2721                              <1>         ;mov    ecx, 80*2
  2722                              <1>         mov	cl, 80*2
  2723                              <1>         add     edi, ecx
  2724                              <1> 	dec	dh
  2725                              <1> 	jnz	short n3x ; 16/01/2016
  2726                              <1> 	;
  2727                              <1> 	cmp	bl, [active_page]
  2728                              <1> 	jne	short n6
  2729                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2730                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2731                              <1> 	mov	dx, 03D8h ; always set color card port
  2732                              <1> 	out	dx, al
  2733                              <1> n6:
  2734                              <1> 	retn
  2735                              <1> 
  2736                              <1> %endif
  2737                              <1> 
  2738                              <1> write_c_current:
  2739                              <1> 	; 02/02/2022
  2740                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2741                              <1> 	; 18/01/2014
  2742                              <1> 	; 04/12/2013
  2743                              <1> 	;
  2744                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2745                              <1> 	;
  2746                              <1> 	; WRITE_C_CURRENT
  2747                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2748                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2749                              <1> 	; INPUT	
  2750                              <1> 	;	(AH) = CURRENT CRT MODE
  2751                              <1> 	;	(BH) = DISPLAY PAGE
  2752                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2753                              <1> 	;	(AL) = CHAR TO WRITE
  2754                              <1> 	;	(DS) = DATA SEGMENT
  2755                              <1> 	;	(ES) = REGEN SEGMENT
  2756                              <1> 	; OUTPUT
  2757                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2758                              <1> 
  2759 000015B3 FA                  <1> 	cli		
  2760                              <1> 	; bl = video page
  2761                              <1> 	; al = character
  2762                              <1> 	; ah = color/attribute
  2763                              <1> 	;push	dx
  2764                              <1> 	;push	ax	; save character & attribute/color
  2765                              <1> 	; 02/02/2022
  2766 000015B4 52                  <1> 	push	edx
  2767 000015B5 50                  <1> 	push	eax
  2768 000015B6 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2769                              <1> 	; esi = regen location
  2770                              <1> 	; dx = status port
  2771                              <1> 	;
  2772                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2773                              <1> 	;
  2774                              <1> p41:			; wait for horizontal retrace is low or vertical
  2775 000015BB FB                  <1> 	sti		; enable interrupts first
  2776 000015BC 3A1D[B66C0000]      <1>         cmp     bl, [active_page]
  2777 000015C2 7510                <1> 	jne	short p44 
  2778 000015C4 FA                  <1> 	cli 		; block interrupts for single loop
  2779 000015C5 EC                  <1> 	in	al, dx	; get status from the adapter
  2780 000015C6 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2781 000015C8 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2782 000015CA A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2783 000015CC 75ED                <1> 	jnz	short p41 ; wait until it is
  2784                              <1> p42:			; wait for either retrace high
  2785 000015CE EC                  <1> 	in	al, dx	; get status again
  2786 000015CF A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2787 000015D1 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2788                              <1> p43:	
  2789 000015D3 FB                  <1> 	sti
  2790                              <1> p44:
  2791                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2792                              <1> 	; 02/02/2022
  2793 000015D4 58                  <1> 	pop	eax
  2794 000015D5 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2795                              <1> 			; Retro UNIX 386 v1 feature only!
  2796 000015DB 668906              <1> 	mov	[esi], ax
  2797                              <1> 	;pop	dx
  2798                              <1> 	; 02/02/2022
  2799 000015DE 5A                  <1> 	pop	edx
  2800 000015DF C3                  <1> 	retn
  2801                              <1> 
  2802                              <1> %if 0	; 02/02/2022
  2803                              <1> 
  2804                              <1> set_mode:
  2805                              <1> 	; 02/02/2022
  2806                              <1> 	; 16/01/2016
  2807                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2808                              <1> 	;
  2809                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2810                              <1> 
  2811                              <1> ;------------------------------------------------------
  2812                              <1> ; SET MODE					      :
  2813                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2814                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2815                              <1> ; INPUT						      :
  2816                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2817                              <1> ; OUTPUT					      :
  2818                              <1> ;	NONE					      :
  2819                              <1> ;------------------------------------------------------
  2820                              <1> 
  2821                              <1> 	push	edi ; 16/01/2016
  2822                              <1> 	push	ebx
  2823                              <1> 	push	edx
  2824                              <1> 	push	ecx ; 16/01/2016
  2825                              <1>         push    eax
  2826                              <1> 
  2827                              <1> 	;mov	dx, 03D4h 	; address or color card
  2828                              <1> 	mov	al, 3
  2829                              <1> ;M8:
  2830                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2831                              <1> 	mov	al, 29h
  2832                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2833                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2834                              <1> 	;push	dx  		; save port value
  2835                              <1> 	;add	dx, 4		; point to control register
  2836                              <1> 	mov	dx, 3D8h
  2837                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2838                              <1> 	;pop	dx
  2839                              <1> ;M9:
  2840                              <1> 	mov	ebx, video_params ; initialization table
  2841                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2842                              <1> 	;xchg 	ah, al
  2843                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2844                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2845                              <1> 	
  2846                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2847                              <1> 	; 02/02/2022
  2848                              <1> 	; dx = 3D8h
  2849                              <1> 	xor	ecx, ecx
  2850                              <1> 	mov	cl, 16
  2851                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2852                              <1> M10:			;  initialization loop
  2853                              <1> 	mov	al, ah 	; get 6845 register number
  2854                              <1> 	out	dx, al
  2855                              <1> 	;inc	dx      ; point to data port
  2856                              <1> 	; 02/02/2022
  2857                              <1> 	inc	dl ; 3D9h
  2858                              <1> 	inc	ah	; next register value
  2859                              <1> 	mov	al, [ebx] ; get table value
  2860                              <1> 	out	dx, al	; out to chip
  2861                              <1> 	inc	ebx	; next in table
  2862                              <1> 	;dec	dx	; back to pointer register
  2863                              <1> 	; 02/02/2022
  2864                              <1> 	dec	dl ; 3D8h
  2865                              <1> 	loop	M10	; do the whole table
  2866                              <1> 	
  2867                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2868                              <1> 	;xor	ax, ax  
  2869                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2870                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2871                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2872                              <1> 	; black background, light gray characeter color, space character
  2873                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2874                              <1> ;M13:			  ; clear buffer
  2875                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2876                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2877                              <1> 
  2878                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2879                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2880                              <1> 			 ; prepare to output to video enable port
  2881                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2882                              <1> 	; 02/02/2022
  2883                              <1> 	;mov	dx, 3D8h
  2884                              <1> 	; 
  2885                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2886                              <1> 	mov	al, 29h
  2887                              <1> 	out	dx, al	 ; set video enable port
  2888                              <1> 
  2889                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2890                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2891                              <1> 	;
  2892                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2893                              <1> 	;
  2894                              <1> ;-----	SET CURSOR POSITIONS
  2895                              <1> 	;push	edi
  2896                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2897                              <1> 	mov	edi, cursor_posn
  2898                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2899                              <1> 	xor	eax, eax
  2900                              <1> 	rep 	stosd	; fill with zeroes
  2901                              <1> 	;pop	edi
  2902                              <1> 
  2903                              <1> ;-----	SET UP OVERSCAN REGISTER
  2904                              <1> 	inc	dx	; set overscan port to a default
  2905                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2906                              <1> ;M14:
  2907                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2908                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2909                              <1> 
  2910                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2911                              <1> 	;
  2912                              <1> 	pop	eax
  2913                              <1> 	pop	ecx ; 16/01/2016
  2914                              <1> 	pop	edx
  2915                              <1> 	pop	ebx
  2916                              <1> 	pop	edi ; 16/01/2016
  2917                              <1> 	retn
  2918                              <1> 
  2919                              <1> %endif
  2920                              <1> 	
  2921                              <1> tty_sw:
  2922                              <1> 	; 02/02/2022
  2923                              <1> 	; 30/06/2015
  2924                              <1> 	; 27/06/2015 
  2925                              <1> 	; 07/09/2014
  2926                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2927                              <1> 	;
  2928                              <1> 	; (Modified registers : EAX)
  2929                              <1> 	;
  2930                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2931                              <1> 	;
  2932                              <1> ;act_disp_page:
  2933                              <1> 	; 30/06/2015
  2934                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2935                              <1> 	; 10/12/2013
  2936                              <1> 	; 04/12/2013
  2937                              <1> 	;
  2938                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2939                              <1> 	;
  2940                              <1> 	; ACT_DISP_PAGE
  2941                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2942                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2943                              <1> 	; INPUT
  2944                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2945                              <1> 	; OUTPUT
  2946                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2947                              <1> 
  2948                              <1> 	;cli
  2949                              <1> 
  2950 000015E0 53                  <1> 	push	ebx
  2951                              <1> 	;push	cx
  2952                              <1> 	;push	dx
  2953                              <1> 	; 02/02/2022
  2954 000015E1 51                  <1> 	push	ecx
  2955 000015E2 52                  <1> 	push	edx
  2956                              <1> 	;
  2957 000015E3 A2[B66C0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2958                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2959                              <1> 	;mov	cx, 25*80*2
  2960                              <1> 	; 02/02/2022
  2961 000015E8 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2962                              <1> 	; 27/06/2015
  2963 000015ED 0FB6D8              <1> 	movzx	ebx, al
  2964                              <1> 	; 02/02/2022
  2965 000015F0 89D8                <1> 	mov	eax, ebx
  2966                              <1> 	;
  2967                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2968                              <1> 	;mul 	cx	; display page times regen length
  2969                              <1> 	; 02/02/2022
  2970 000015F2 F7E1                <1> 	mul	ecx	
  2971                              <1> 	; 10/12/2013
  2972 000015F4 66A3[A46C0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2973                              <1> 	;mov	cx, ax	; start address to cx
  2974                              <1> 	; 02/02/2022
  2975 000015FA 89C1                <1> 	mov	ecx, eax
  2976                              <1> 	;sar	cx, 1
  2977                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2978                              <1> 	; 02/02/2022
  2979 000015FC D1E9                <1> 	shr	ecx, 1
  2980 000015FE B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2981 00001600 E8EFFEFFFF          <1> 	call	m16
  2982                              <1> 	;sal	bx, 1
  2983                              <1> 	; 01/09/2014
  2984 00001605 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2985 00001607 81C3[A66C0000]      <1> 	add	ebx, cursor_posn
  2986 0000160D 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2987 00001610 E8CDFEFFFF          <1> 	call	m18
  2988                              <1> 	;
  2989                              <1> 	;pop	dx
  2990                              <1> 	;pop	cx
  2991                              <1> 	; 02/02/2022
  2992 00001615 5A                  <1> 	pop	edx
  2993 00001616 59                  <1> 	pop	ecx
  2994 00001617 5B                  <1> 	pop	ebx
  2995                              <1> 	;
  2996                              <1> 	;sti
  2997                              <1> 	;
  2998 00001618 C3                  <1> 	retn
  2999                              <1> 
  3000                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  3001                              <1> 
  3002                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1882                                  
  1883                                  setup_rtc_int:
  1884                                  ; source: http://wiki.osdev.org/RTC
  1885 00001619 FA                      	cli		; disable interrupts
  1886                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1887                                  	; in order to change this ...
  1888                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1889                                  	; (rate must be above 2 and not over 15)
  1890                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1891 0000161A B08A                    	mov	al, 8Ah 
  1892 0000161C E670                    	out	70h, al ; set index to register A, disable NMI
  1893 0000161E 90                      	nop
  1894 0000161F E471                    	in	al, 71h ; get initial value of register A
  1895 00001621 88C4                    	mov 	ah, al
  1896 00001623 80E4F0                  	and	ah, 0F0h
  1897 00001626 B08A                    	mov	al, 8Ah 
  1898 00001628 E670                    	out	70h, al ; reset index to register A
  1899 0000162A 88E0                    	mov	al, ah
  1900 0000162C 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1901 0000162E E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1902                                  	; enable RTC interrupt
  1903 00001630 B08B                    	mov	al, 8Bh ;
  1904 00001632 E670                    	out	70h, al ; select register B and disable NMI
  1905 00001634 90                      	nop
  1906 00001635 E471                    	in	al, 71h ; read the current value of register B
  1907 00001637 88C4                    	mov	ah, al  ;
  1908 00001639 B08B                    	mov 	al, 8Bh ;
  1909 0000163B E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1910 0000163D 88E0                    	mov	al, ah  ;
  1911 0000163F 0C40                    	or	al, 40h ;
  1912 00001641 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1913 00001643 FB                      	sti
  1914 00001644 C3                      	retn
  1915                                  
  1916                                  ; Write memory information
  1917                                  ; Temporary Code
  1918                                  ; 06/11/2014
  1919                                  ; 14/08/2015 
  1920                                  memory_info:	
  1921 00001645 A1[8C6C0000]            	mov	eax, [memory_size] ; in pages
  1922 0000164A 50                      	push	eax
  1923 0000164B C1E00C                  	shl	eax, 12		   ; in bytes
  1924 0000164E BB0A000000              	mov	ebx, 10
  1925 00001653 89D9                    	mov	ecx, ebx	   ; 10
  1926 00001655 BE[F1680000]            	mov	esi, mem_total_b_str	
  1927 0000165A E8AE000000              	call	bintdstr
  1928 0000165F 58                      	pop	eax
  1929 00001660 B107                    	mov	cl, 7
  1930 00001662 BE[15690000]            	mov	esi, mem_total_p_str
  1931 00001667 E8A1000000              	call	bintdstr	
  1932                                  	; 14/08/2015
  1933 0000166C E8B9000000              	call	calc_free_mem
  1934                                  	; edx = calculated free pages
  1935                                  	; ecx = 0
  1936 00001671 A1[906C0000]            	mov 	eax, [free_pages]
  1937 00001676 39D0                    	cmp	eax, edx ; calculated free mem value 
  1938                                  		; and initial free mem value are same or not?
  1939 00001678 751D                    	jne 	short pmim ; print mem info with '?' if not
  1940 0000167A 52                      	push 	edx ; free memory in pages	
  1941                                  	;mov 	eax, edx
  1942 0000167B C1E00C                  	shl	eax, 12 ; convert page count
  1943                                  			; to byte count
  1944 0000167E B10A                    	mov	cl, 10
  1945 00001680 BE[35690000]            	mov	esi, free_mem_b_str
  1946 00001685 E883000000              	call	bintdstr
  1947 0000168A 58                      	pop	eax
  1948 0000168B B107                    	mov	cl, 7
  1949 0000168D BE[59690000]            	mov	esi, free_mem_p_str
  1950 00001692 E876000000              	call	bintdstr
  1951                                  pmim:
  1952 00001697 BE[DF680000]            	mov	esi, msg_memory_info
  1953                                  pmim_nb:	
  1954 0000169C AC                      	lodsb
  1955 0000169D 08C0                    	or	al, al
  1956 0000169F 740D                    	jz	short pmim_ok
  1957 000016A1 56                      	push	esi
  1958 000016A2 31DB                    	xor	ebx, ebx ; 0
  1959                                  			; Video page 0 (bl=0)
  1960 000016A4 B407                    	mov	ah, 07h ; Black background, 
  1961                                  			; light gray forecolor
  1962 000016A6 E816FDFFFF              	call	write_tty
  1963 000016AB 5E                      	pop	esi
  1964 000016AC EBEE                    	jmp	short pmim_nb
  1965                                  pmim_ok:
  1966 000016AE C3                      	retn
  1967                                  
  1968                                  ; Convert binary number to hexadecimal string
  1969                                  ; 10/05/2015  
  1970                                  ; dsectpm.s (28/02/2015)
  1971                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1972                                  ; 01/12/2014
  1973                                  ; 25/11/2014
  1974                                  ;
  1975                                  bytetohex:
  1976                                  	; INPUT ->
  1977                                  	; 	AL = byte (binary number)
  1978                                  	; OUTPUT ->
  1979                                  	;	AX = hexadecimal string
  1980                                  	;
  1981 000016AF 53                      	push	ebx
  1982 000016B0 31DB                    	xor	ebx, ebx
  1983 000016B2 88C3                    	mov	bl, al
  1984 000016B4 C0EB04                  	shr	bl, 4
  1985 000016B7 8A9B[FD160000]          	mov	bl, [ebx+hexchrs]
  1986 000016BD 86D8                    	xchg	bl, al
  1987 000016BF 80E30F                  	and	bl, 0Fh
  1988 000016C2 8AA3[FD160000]          	mov	ah, [ebx+hexchrs]
  1989 000016C8 5B                      	pop	ebx	
  1990 000016C9 C3                      	retn
  1991                                  
  1992                                  wordtohex:
  1993                                  	; INPUT ->
  1994                                  	; 	AX = word (binary number)
  1995                                  	; OUTPUT ->
  1996                                  	;	EAX = hexadecimal string
  1997                                  	;
  1998 000016CA 53                      	push	ebx
  1999 000016CB 31DB                    	xor	ebx, ebx
  2000 000016CD 86E0                    	xchg	ah, al
  2001 000016CF 6650                    	push	ax
  2002 000016D1 88E3                    	mov	bl, ah
  2003 000016D3 C0EB04                  	shr	bl, 4
  2004 000016D6 8A83[FD160000]          	mov	al, [ebx+hexchrs]
  2005 000016DC 88E3                    	mov	bl, ah
  2006 000016DE 80E30F                  	and	bl, 0Fh
  2007 000016E1 8AA3[FD160000]          	mov	ah, [ebx+hexchrs]
  2008 000016E7 C1E010                  	shl	eax, 16
  2009 000016EA 6658                    	pop	ax
  2010 000016EC 5B                      	pop	ebx
  2011 000016ED EBC0                    	jmp	short bytetohex
  2012                                  	;mov	bl, al
  2013                                  	;shr	bl, 4
  2014                                  	;mov	bl, [ebx+hexchrs]
  2015                                  	;xchg	bl, al	 	
  2016                                  	;and	bl, 0Fh
  2017                                  	;mov	ah, [ebx+hexchrs]
  2018                                  	;pop	ebx	
  2019                                  	;retn
  2020                                  
  2021                                  dwordtohex:
  2022                                  	; INPUT ->
  2023                                  	; 	EAX = dword (binary number)
  2024                                  	; OUTPUT ->
  2025                                  	;	EDX:EAX = hexadecimal string
  2026                                  	;
  2027 000016EF 50                      	push	eax
  2028 000016F0 C1E810                  	shr	eax, 16
  2029 000016F3 E8D2FFFFFF              	call	wordtohex
  2030 000016F8 89C2                    	mov	edx, eax
  2031 000016FA 58                      	pop	eax
  2032                                  	;call	wordtohex
  2033                                  	;retn
  2034                                  	; 02/01/2022
  2035 000016FB EBCD                    	jmp	short wordtohex
  2036                                  
  2037                                  ; 10/05/2015
  2038                                  hex_digits:
  2039                                  hexchrs:
  2040 000016FD 303132333435363738-     	db '0123456789ABCDEF'
  2040 00001706 39414243444546     
  2041                                  
  2042                                  ; Convert binary number to decimal/numeric string
  2043                                  ; 06/11/2014
  2044                                  ; Temporary Code
  2045                                  ;
  2046                                  
  2047                                  bintdstr:
  2048                                  	; EAX = binary number
  2049                                  	; ESI = decimal/numeric string address
  2050                                  	; EBX = divisor (10)
  2051                                  	; ECX = string length (<=10)
  2052 0000170D 01CE                    	add	esi, ecx
  2053                                  btdstr0:
  2054 0000170F 4E                      	dec	esi
  2055 00001710 31D2                    	xor	edx, edx
  2056 00001712 F7F3                    	div	ebx
  2057 00001714 80C230                  	add	dl, 30h
  2058 00001717 8816                    	mov	[esi], dl
  2059 00001719 FEC9                    	dec	cl
  2060 0000171B 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2061 0000171D 09C0                    	or	eax, eax
  2062 0000171F 75EE                    	jnz	short btdstr0
  2063                                  btdstr1:
  2064 00001721 4E                      	dec	esi
  2065 00001722 C60620                          mov     byte [esi], 20h ; blank space
  2066 00001725 FEC9                    	dec	cl
  2067 00001727 75F8                    	jnz	short btdstr1
  2068                                  btdstr2:
  2069 00001729 C3                      	ret
  2070                                  
  2071                                  ; Calculate free memory pages on M.A.T.
  2072                                  ; 06/11/2014
  2073                                  ; Temporary Code
  2074                                  ;
  2075                                  
  2076                                  calc_free_mem:
  2077 0000172A 31D2                    	xor	edx, edx
  2078                                  	;xor	ecx, ecx
  2079                                  	;mov	cx, [mat_size] ; in pages
  2080                                  	; 02/01/2022
  2081 0000172C 8B0D[A06C0000]          	mov	ecx, [mat_size] ; in pages
  2082 00001732 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2083 00001735 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2084                                  cfm0:
  2085 0000173A AD                      	lodsd
  2086 0000173B 51                      	push	ecx
  2087 0000173C B920000000              	mov	ecx, 32
  2088                                  cfm1:
  2089 00001741 D1E8                    	shr	eax, 1
  2090 00001743 7301                    	jnc	short cfm2
  2091 00001745 42                      	inc	edx
  2092                                  cfm2:
  2093 00001746 E2F9                    	loop	cfm1
  2094 00001748 59                      	pop	ecx
  2095 00001749 E2EF                    	loop	cfm0
  2096 0000174B C3                      	ret
  2097                                  
  2098                                  %include 'diskio.inc'  ; 07/03/2015
  2099                              <1> ; Retro UNIX 386 v1.1 Kernel - DISKIO.INC
  2100                              <1> ; Last Modification: 24/12/2021
  2101                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2102                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2103                              <1> 
  2104                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2105                              <1> 
  2106                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2107                              <1> 
  2108                              <1> ; 06/02/2015
  2109                              <1> diskette_io:
  2110 0000174C 9C                  <1> 	pushfd
  2111 0000174D 0E                  <1> 	push 	cs
  2112 0000174E E809000000          <1> 	call 	DISKETTE_IO_1
  2113 00001753 C3                  <1> 	retn
  2114                              <1> 	
  2115                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2116                              <1> ;//////////////////////////////////////////////////////
  2117                              <1> 
  2118                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2119                              <1> ; 20/02/2015
  2120                              <1> ; 06/02/2015 (unix386.s)
  2121                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2122                              <1> ;
  2123                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2124                              <1> ;
  2125                              <1> ; ADISK.EQU
  2126                              <1> 
  2127                              <1> ;----- Wait control constants 
  2128                              <1> 
  2129                              <1> ;amount of time to wait while RESET is active.
  2130                              <1> 
  2131                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2132                              <1> 					;at 250 KBS xfer rate.
  2133                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2134                              <1> 
  2135                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2136                              <1> 					;status register to become valid
  2137                              <1> 					;before re-reading.
  2138                              <1> 
  2139                              <1> ;After sending a byte to NEC, status register may remain
  2140                              <1> ;incorrectly set for 24 us.
  2141                              <1> 
  2142                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2143                              <1> 					;RQM low.
  2144                              <1> 
  2145                              <1> ; COMMON.MAC
  2146                              <1> ;
  2147                              <1> ;	Timing macros
  2148                              <1> ;
  2149                              <1> 
  2150                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2151                              <1> 		jmp short $+2
  2152                              <1> %endmacro		
  2153                              <1> 
  2154                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2155                              <1> 		jmp short $+2
  2156                              <1> 		jmp short $+2
  2157                              <1> %endmacro
  2158                              <1> 
  2159                              <1> %macro		NEWIODELAY 0
  2160                              <1> 		out	0EBh,al
  2161                              <1> %endmacro 
  2162                              <1> 
  2163                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2164                              <1> ;;; WAIT_FOR_MEM
  2165                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2166                              <1> ;WAIT_FDU_INT_HI	equ	1
  2167                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2168                              <1> ;;; WAIT_FOR_PORT
  2169                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2170                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2171                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2172                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2173                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2174                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2175                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2176                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2177                              <1> ;;; WAIT_REFRESH
  2178                              <1> ;amount of time to wait for head settle, per unit in parameter
  2179                              <1> ;table = 1 ms.
  2180                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2181                              <1> 
  2182                              <1> 
  2183                              <1> ; //////////////// DISKETTE I/O ////////////////
  2184                              <1> 
  2185                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2186                              <1> 
  2187                              <1> ;----------------------------------------
  2188                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2189                              <1> ;----------------------------------------
  2190                              <1> 
  2191                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2192                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2193                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2194                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2195                              <1> 
  2196                              <1> ;----------------------------------------
  2197                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2198                              <1> ;-------------------------------------------------------------------------------
  2199                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2200                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2201                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2202                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2203                              <1> 
  2204                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2205                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2206                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2207                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2208                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2209                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2210                              <1> 
  2211                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2212                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2213                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2214                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2215                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2216                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2217                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2218                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2219                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2220                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2221                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2222                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2223                              <1> 
  2224                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2225                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2226                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2227                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2228                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2229                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2230                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2231                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2232                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2233                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2234                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2235                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2236                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2237                              <1> 
  2238                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2239                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2240                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2241                              <1> 
  2242                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2243                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2244                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2245                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2246                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2247                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2248                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2249                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2250                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2251                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2252                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2253                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2254                              <1> 
  2255                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2256                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2257                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2258                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2259                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2260                              <1> 
  2261                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2262                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2263                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2264                              <1> INTA01		EQU	021H		; 8259 PORT
  2265                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2266                              <1> INTB01		EQU	0A1H		;
  2267                              <1> 
  2268                              <1> ;-------------------------------------------------------------------------------
  2269                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2270                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2271                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2272                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2273                              <1> ;-------------------------------------------------------------------------------
  2274                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2275                              <1> 
  2276                              <1> ;-------------------------------------------------------------------------------
  2277                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2278                              <1> 
  2279                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2280                              <1> ; (unix386.s <-- dsectrm2.s)
  2281                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2282                              <1> 
  2283                              <1> ; 10/12/2014
  2284                              <1> ;
  2285                              <1> ;int40h:
  2286                              <1> ;	pushf
  2287                              <1> ;	push 	cs
  2288                              <1> ;	;cli
  2289                              <1> ;	call 	DISKETTE_IO_1
  2290                              <1> ;	retn
  2291                              <1> 
  2292                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2293                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2294                              <1> ;
  2295                              <1> 
  2296                              <1> ;-- INT13H ---------------------------------------------------------------------
  2297                              <1> ; DISKETTE I/O
  2298                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2299                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2300                              <1> ; INPUT
  2301                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2302                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2303                              <1> ;		ON ALL DRIVES
  2304                              <1> ;------------------------------------------------------------------------------- 
  2305                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2306                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2307                              <1> ;-------------------------------------------------------------------------------
  2308                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2309                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2310                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2311                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2312                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2313                              <1> ;		320/360	320/360	    0-39
  2314                              <1> ;		320/360	1.2M	    0-39
  2315                              <1> ;		1.2M	1.2M	    0-79
  2316                              <1> ;		720K	720K	    0-79
  2317                              <1> ;		1.44M	1.44M	    0-79	
  2318                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2319                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2320                              <1> ;		320/360	320/360	     1-8/9
  2321                              <1> ;		320/360	1.2M	     1-8/9
  2322                              <1> ;		1.2M	1.2M	     1-15
  2323                              <1> ;		720K	720K	     1-9
  2324                              <1> ;		1.44M	1.44M	     1-18		
  2325                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2326                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2327                              <1> ;		320/360	320/360	        8/9
  2328                              <1> ;		320/360	1.2M	        8/9
  2329                              <1> ;		1.2M	1.2M		15
  2330                              <1> ;		720K	720K		9
  2331                              <1> ;		1.44M	1.44M		18
  2332                              <1> ;
  2333                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2334                              <1> ;
  2335                              <1> ;-------------------------------------------------------------------------------
  2336                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2337                              <1> ;-------------------------------------------------------------------------------
  2338                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2339                              <1> ;-------------------------------------------------------------------------------
  2340                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2341                              <1> ;-------------------------------------------------------------------------------
  2342                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2343                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2344                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2345                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2346                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2347                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2348                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2349                              <1> ;		READ/WRITE ACCESS.
  2350                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2351                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2352                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2353                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2354                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2355                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2356                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2357                              <1> ;
  2358                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2359                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2360                              <1> ;		---------------------------------------------
  2361                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2362                              <1> ;		---------------------------------------------
  2363                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2364                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2365                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2366                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2367                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2368                              <1> ;		---------------------------------------------
  2369                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2370                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2371                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2372                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2373                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2374                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2375                              <1> ;-------------------------------------------------------------------------------
  2376                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2377                              <1> ;	REGISTERS
  2378                              <1> ;	  INPUT
  2379                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2380                              <1> ;	  OUTPUT
  2381                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2382                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2383                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2384                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2385                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2386                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2387                              <1> ;	    (BH) - 0
  2388                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2389                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2390                              <1> ;	    (AX) - 0
  2391                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2392                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2393                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2394                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2395                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2396                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2397                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2398                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2399                              <1> ;-------------------------------------------------------------------------------
  2400                              <1> ;	(AH)= 15H  READ DASD TYPE
  2401                              <1> ;	OUTPUT REGISTERS
  2402                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2403                              <1> ;		00 - DRIVE NOT PRESENT	
  2404                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2405                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2406                              <1> ;		03 - RESERVED (FIXED DISK)
  2407                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2408                              <1> ;-------------------------------------------------------------------------------
  2409                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2410                              <1> ;	OUTPUT REGISTERS
  2411                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2412                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2413                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2414                              <1> ;-------------------------------------------------------------------------------
  2415                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2416                              <1> ;	INPUT REGISTERS
  2417                              <1> ;	(AL) -	00 - NOT USED	
  2418                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2419                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2420                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2421                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2422                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2423                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2424                              <1> ;-------------------------------------------------------------------------------
  2425                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2426                              <1> ;	INPUT REGISTERS
  2427                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2428                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2429                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2430                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2431                              <1> ;	OUTPUT REGISTERS:
  2432                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2433                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2434                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2435                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2436                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2437                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2438                              <1> ;-------------------------------------------------------------------------------
  2439                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2440                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2441                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2442                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2443                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2444                              <1> ;		CHANGE ERROR CODE
  2445                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2446                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2447                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2448                              <1> ;
  2449                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2450                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2451                              <1> ;-------------------------------------------------------------------------------
  2452                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2453                              <1> ;	AH = STATUS OF OPERATION
  2454                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2455                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2456                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2457                              <1> ;		TYPE AH=(15)).
  2458                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2459                              <1> ;	FOR READ/WRITE/VERIFY
  2460                              <1> ;		DS,BX,DX,CX PRESERVED
  2461                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2462                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2463                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2464                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2465                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2466                              <1> ;-------------------------------------------------------------------------------
  2467                              <1> ;
  2468                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2469                              <1> ;
  2470                              <1> ;   -----------------------------------------------------------------
  2471                              <1> ;   |       |       |       |       |       |       |       |       |
  2472                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2473                              <1> ;   |       |       |       |       |       |       |       |       |
  2474                              <1> ;   -----------------------------------------------------------------
  2475                              <1> ;	|	|	|	|	|	|	|	|
  2476                              <1> ;	|	|	|	|	|	-----------------
  2477                              <1> ;	|	|	|	|	|		|
  2478                              <1> ;	|	|	|	|    RESERVED		|
  2479                              <1> ;	|	|	|	|		  PRESENT STATE
  2480                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2481                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2482                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2483                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2484                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2485                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2486                              <1> ;	|	|	|	|	110: RESERVED
  2487                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2488                              <1> ;	|	|	|	|
  2489                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2490                              <1> ;	|	|	|
  2491                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2492                              <1> ;	|	|			DRIVE)
  2493                              <1> ;	|	|
  2494                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2495                              <1> ;
  2496                              <1> ;						00: 500 KBS
  2497                              <1> ;						01: 300 KBS
  2498                              <1> ;						10: 250 KBS
  2499                              <1> ;						11: RESERVED
  2500                              <1> ;
  2501                              <1> ;
  2502                              <1> ;-------------------------------------------------------------------------------
  2503                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2504                              <1> ;-------------------------------------------------------------------------------
  2505                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2506                              <1> ;-------------------------------------------------------------------------------
  2507                              <1> 
  2508                              <1> struc MD
  2509 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2510 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2511 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2512 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2513 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2514 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2515 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2516 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2517 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2518 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2519 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2520 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2521 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2522                              <1> endstruc
  2523                              <1> 
  2524                              <1> BIT7OFF	EQU	7FH
  2525                              <1> BIT7ON	EQU	80H
  2526                              <1> 
  2527                              <1> ;;int13h: ; 16/02/2015
  2528                              <1> ;; 16/02/2015 - 21/02/2015
  2529                              <1> int40h:
  2530 00001754 9C                  <1> 	pushfd
  2531 00001755 0E                  <1> 	push 	cs
  2532 00001756 E801000000          <1> 	call 	DISKETTE_IO_1
  2533 0000175B C3                  <1> 	retn	
  2534                              <1> 
  2535                              <1> DISKETTE_IO_1:
  2536                              <1> 
  2537 0000175C FB                  <1> 	STI				; INTERRUPTS BACK ON
  2538 0000175D 55                  <1> 	PUSH	eBP			; USER REGISTER
  2539 0000175E 57                  <1> 	PUSH	eDI			; USER REGISTER
  2540 0000175F 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2541 00001760 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2542 00001761 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2543 00001762 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2544                              <1> 					; [BP]   = SECTOR #
  2545                              <1> 					; [BP+1] = TRACK #
  2546                              <1> 					; [BP+2] = BUFFER OFFSET
  2547                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2548                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2549                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2550                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2551                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2552                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2553                              <1> 					; BH/[BP+3] = 0
  2554                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2555                              <1> 					; DH/[BP+5] = MAX HEAD #
  2556                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2557 00001764 06                  <1> 	push	es ; 06/02/2015	
  2558 00001765 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2559 00001766 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2560                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2561                              <1> 	;mov	cx, cs
  2562                              <1> 	;mov	ds, cx
  2563 00001767 66B91000            <1> 	mov	cx, KDATA
  2564 0000176B 8ED9                <1>         mov     ds, cx
  2565 0000176D 8EC1                <1>         mov     es, cx
  2566                              <1> 
  2567                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2568 0000176F 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2569 00001772 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2570 00001774 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2571                              <1> OK_FUNC:
  2572 00001776 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2573 00001779 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2574 0000177B 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2575 0000177E 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2576 00001780 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2577 00001783 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2578 00001785 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2579                              <1> OK_DRV:
  2580 00001787 31C9                <1> 	xor	ecx, ecx
  2581                              <1> 	;mov	esi, ecx ; 08/02/2015
  2582                              <1> 	; 24/12/2021
  2583 00001789 89CE                <1> 	mov	esi, ecx
  2584 0000178B 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2585 0000178D 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2586                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2587                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2588 0000178F C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2589 00001792 BB[CA170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2590 00001797 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2591 00001799 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2592 0000179B 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2593 0000179D 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2594 000017A0 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2595                              <1> 	;
  2596                              <1> 	; 11/12/2014
  2597 000017A3 8815[71670000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2598                              <1> 	;
  2599 000017A9 8A25[0C6D0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2600 000017AF C605[0C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2601                              <1> 
  2602                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2603                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2604                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2605                              <1> ;
  2606                              <1> ;		DI	: DRIVE #
  2607                              <1> ;		SI-HI	: HEAD #
  2608                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2609                              <1> ;		ES	: BUFFER SEGMENT
  2610                              <1> ;		[BP]	: SECTOR #
  2611                              <1> ;		[BP+1]	: TRACK #
  2612                              <1> ;		[BP+2]	: BUFFER OFFSET
  2613                              <1> ;
  2614                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2615                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2616                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2617                              <1> ;	SPECIFIC ERROR CODE.
  2618                              <1> ;
  2619                              <1> 					; (AH) = @DSKETTE_STATUS
  2620 000017B6 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2621 000017B8 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2622 000017B9 1F                  <1> 	POP	DS
  2623 000017BA 07                  <1> 	pop	es	; 06/02/2015
  2624 000017BB 59                  <1> 	POP	eCX
  2625 000017BC 5B                  <1> 	POP	eBX
  2626 000017BD 5A                  <1> 	POP	eDX
  2627 000017BE 5F                  <1> 	POP	eDI
  2628 000017BF 89E5                <1> 	MOV	eBP, eSP
  2629 000017C1 50                  <1> 	PUSH	eAX
  2630 000017C2 9C                  <1> 	PUSHFd
  2631 000017C3 58                  <1> 	POP	eAX
  2632                              <1> 	;MOV	[BP+6], AX
  2633 000017C4 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2634 000017C7 58                  <1> 	POP	eAX
  2635 000017C8 5D                  <1> 	POP	eBP
  2636 000017C9 CF                  <1> 	IRETd
  2637                              <1> 
  2638                              <1> ;-------------------------------------------------------------------------------
  2639                              <1> ; DW --> dd (06/02/2015)
  2640 000017CA [2E180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2641 000017CE [A3180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2642 000017D2 [B3180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2643 000017D6 [C4180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2644 000017DA [D5180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2645 000017DE [E6180000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2646 000017E2 [6A190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2647 000017E6 [6A190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2648 000017EA [76190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2649 000017EE [6A190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2650 000017F2 [6A190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2651 000017F6 [6A190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2652 000017FA [6A190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2653 000017FE [6A190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2654 00001802 [6A190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2655 00001806 [6A190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2656 0000180A [6A190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2657 0000180E [6A190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2658 00001812 [6A190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2659 00001816 [6A190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2660 0000181A [6A190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2661 0000181E [351A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2662 00001822 [5D1A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2663 00001826 [961A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2664 0000182A [171B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2665                              <1> FNC_TAE EQU     $                       ; END
  2666                              <1> 
  2667                              <1> ;-------------------------------------------------------------------------------
  2668                              <1> ; DISK_RESET	(AH = 00H)	
  2669                              <1> ;		RESET THE DISKETTE SYSTEM.
  2670                              <1> ;
  2671                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2672                              <1> ;-------------------------------------------------------------------------------
  2673                              <1> DSK_RESET:
  2674 0000182E 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2675 00001832 FA                  <1> 	CLI				; NO INTERRUPTS
  2676 00001833 A0[0A6D0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2677 00001838 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2678 0000183A C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2679                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2680 0000183D 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2681 0000183F EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2682 00001840 C605[096D0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2683                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2684                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2685                              <1> 					;      PULSE WIDTH)
  2686                              <1> 	; 19/12/2014
  2687                              <1> 	NEWIODELAY
  2160 00001847 E6EB                <2>  out 0EBh,al
  2688                              <1> 
  2689                              <1> 	; 17/12/2014 
  2690                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2691 00001849 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2692                              <1> wdw1:
  2693                              <1> 	NEWIODELAY   ; 27/02/2015
  2160 0000184E E6EB                <2>  out 0EBh,al
  2694 00001850 E2FC                <1> 	loop	wdw1
  2695                              <1> 	;
  2696 00001852 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2697 00001854 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2698                              <1> 	; 16/12/2014
  2699                              <1> 	IODELAY
  2155 00001855 EB00                <2>  jmp short $+2
  2156 00001857 EB00                <2>  jmp short $+2
  2700                              <1> 	;
  2701                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2702 00001859 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2703 0000185E 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2704 00001860 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2705                              <1> NXT_DRV:
  2706                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2707                              <1> 	; 24/12/2021
  2708 00001864 51                  <1> 	push	ecx
  2709 00001865 B8[99180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2710 0000186A 50                  <1> 	PUSH	eAX			; "
  2711 0000186B B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2712 0000186D E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2713 00001872 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2714 00001873 E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2715                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2716                              <1> 	; 24/12/2021
  2717 00001878 59                  <1> 	pop	ecx
  2718 00001879 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2719 0000187B 3A0D[0D6D0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2720 00001881 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2721 00001883 FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2722 00001885 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2723 00001888 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2724                              <1> 	;
  2725 0000188A E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2726                              <1> RESBAC:
  2727 0000188F E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2728                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2729                              <1> 	; 24/12/2021
  2730 00001894 89F3                <1> 	mov	ebx, esi
  2731 00001896 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2732 00001898 C3                  <1> 	RETn		
  2733                              <1> DR_POP_ERR:
  2734                              <1> 	;POP	CX			; CLEAR STACK
  2735                              <1> 	; 24/12/2021
  2736 00001899 59                  <1> 	pop	ecx
  2737                              <1> DR_ERR:
  2738 0000189A 800D[0C6D0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2739 000018A1 EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2740                              <1> 
  2741                              <1> ;-------------------------------------------------------------------------------
  2742                              <1> ; DISK_STATUS	(AH = 01H)
  2743                              <1> ;	DISKETTE STATUS.
  2744                              <1> ;
  2745                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2746                              <1> ;
  2747                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2748                              <1> ;-------------------------------------------------------------------------------
  2749                              <1> DSK_STATUS:
  2750 000018A3 8825[0C6D0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2751 000018A9 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2752                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2753                              <1> 	; 24/12/2021
  2754 000018AE 89F3                <1> 	mov	ebx, esi
  2755 000018B0 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2756 000018B2 C3                  <1> 	RETn		
  2757                              <1> 
  2758                              <1> ;-------------------------------------------------------------------------------
  2759                              <1> ; DISK_READ	(AH = 02H)	
  2760                              <1> ;	DISKETTE READ.
  2761                              <1> ;
  2762                              <1> ; ON ENTRY:	DI	: DRIVE #
  2763                              <1> ;		SI-HI	: HEAD #
  2764                              <1> ;		SI-LOW	: # OF SECTORS
  2765                              <1> ;		ES	: BUFFER SEGMENT
  2766                              <1> ;		[BP]	: SECTOR #
  2767                              <1> ;		[BP+1]	: TRACK #
  2768                              <1> ;		[BP+2]	: BUFFER OFFSET
  2769                              <1> ;
  2770                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2771                              <1> ;-------------------------------------------------------------------------------
  2772                              <1> 
  2773                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2774                              <1> 
  2775                              <1> DSK_READ:
  2776 000018B3 8025[0A6D0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2777 000018BA 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2778 000018BE E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2779 000018C3 C3                  <1> 	RETn
  2780                              <1> 
  2781                              <1> ;-------------------------------------------------------------------------------
  2782                              <1> ; DISK_WRITE	(AH = 03H)
  2783                              <1> ;	DISKETTE WRITE.
  2784                              <1> ;
  2785                              <1> ; ON ENTRY:	DI	: DRIVE #
  2786                              <1> ;		SI-HI	: HEAD #
  2787                              <1> ;		SI-LOW	: # OF SECTORS
  2788                              <1> ;		ES	: BUFFER SEGMENT
  2789                              <1> ;		[BP]	: SECTOR #
  2790                              <1> ;		[BP+1]	: TRACK #
  2791                              <1> ;		[BP+2]	: BUFFER OFFSET
  2792                              <1> ;
  2793                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2794                              <1> ;-------------------------------------------------------------------------------
  2795                              <1> 
  2796                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2797                              <1> 
  2798                              <1> DSK_WRITE:
  2799 000018C4 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2800 000018C8 800D[0A6D0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2801 000018CF E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2802 000018D4 C3                  <1> 	RETn
  2803                              <1> 
  2804                              <1> ;-------------------------------------------------------------------------------
  2805                              <1> ; DISK_VERF	(AH = 04H)
  2806                              <1> ;	DISKETTE VERIFY.
  2807                              <1> ;
  2808                              <1> ; ON ENTRY:	DI	: DRIVE #
  2809                              <1> ;		SI-HI	: HEAD #
  2810                              <1> ;		SI-LOW	: # OF SECTORS
  2811                              <1> ;		ES	: BUFFER SEGMENT
  2812                              <1> ;		[BP]	: SECTOR #
  2813                              <1> ;		[BP+1]	: TRACK #
  2814                              <1> ;		[BP+2]	: BUFFER OFFSET
  2815                              <1> ;
  2816                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2817                              <1> ;-------------------------------------------------------------------------------
  2818                              <1> DSK_VERF:
  2819 000018D5 8025[0A6D0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2820 000018DC 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2821 000018E0 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2822 000018E5 C3                  <1> 	RETn
  2823                              <1> 
  2824                              <1> ;-------------------------------------------------------------------------------
  2825                              <1> ; DISK_FORMAT	(AH = 05H)
  2826                              <1> ;	DISKETTE FORMAT.
  2827                              <1> ;
  2828                              <1> ; ON ENTRY:	DI	: DRIVE #
  2829                              <1> ;		SI-HI	: HEAD #
  2830                              <1> ;		SI-LOW	: # OF SECTORS
  2831                              <1> ;		ES	: BUFFER SEGMENT
  2832                              <1> ;		[BP]	: SECTOR #
  2833                              <1> ;		[BP+1]	: TRACK #
  2834                              <1> ;		[BP+2]	: BUFFER OFFSET
  2835                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2836                              <1> ;
  2837                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2838                              <1> ;-------------------------------------------------------------------------------
  2839                              <1> DSK_FORMAT:
  2840 000018E6 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2841 000018EB E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2842 000018F0 800D[0A6D0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2843 000018F7 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2844 000018FC 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2845 000018FE E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2846 00001903 E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2847 00001908 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2848 0000190A E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2849                              <1> FM_WR:
  2850 0000190F E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2851 00001914 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2852 00001916 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2853 00001918 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2854 0000191D 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2855 0000191F B8[5B190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2856 00001924 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2857 00001925 B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2858 00001927 E80E090000          <1> 	CALL	GET_PARM
  2859 0000192C E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2860 00001931 B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2861 00001933 E802090000          <1> 	CALL	GET_PARM
  2862 00001938 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2863 0000193D B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2864 0000193F E8F6080000          <1> 	CALL	GET_PARM
  2865 00001944 E8F7090000          <1> 	CALL	NEC_OUTPUT
  2866 00001949 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2867 0000194B E8EA080000          <1> 	CALL	GET_PARM
  2868 00001950 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2869 00001955 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2870 00001956 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2871                              <1> FM_DON:
  2872 0000195B E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2873 00001960 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2874                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2875 00001965 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2876 00001967 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2877 00001969 C3                  <1> 	RETn
  2878                              <1> 
  2879                              <1> ;-------------------------------------------------------------------------------
  2880                              <1> ; FNC_ERR
  2881                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2882                              <1> ;	SET BAD COMMAND IN STATUS.
  2883                              <1> ;
  2884                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2885                              <1> ;-------------------------------------------------------------------------------
  2886                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2887                              <1> 	;MOV	AX,SI			; RESTORE AL
  2888                              <1> 	; 24/12/2021
  2889 0000196A 89F0                <1> 	mov	eax, esi
  2890 0000196C B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2891 0000196E 8825[0C6D0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2892 00001974 F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2893 00001975 C3                  <1> 	RETn
  2894                              <1> 
  2895                              <1> ;-------------------------------------------------------------------------------
  2896                              <1> ; DISK_PARMS	(AH = 08H)	
  2897                              <1> ;	READ DRIVE PARAMETERS.
  2898                              <1> ;
  2899                              <1> ; ON ENTRY:	DI : DRIVE #
  2900                              <1> ;
  2901                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2902                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2903                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2904                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2905                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2906                              <1> ;		BH/[BP+3] = 0
  2907                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2908                              <1> ;		DH/[BP+5] = MAX HEAD #
  2909                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2910                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2911                              <1> ;		AX        = 0
  2912                              <1> ;
  2913                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2914                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2915                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2916                              <1> ;		       CALLER.
  2917                              <1> ;-------------------------------------------------------------------------------
  2918                              <1> DSK_PARMS:
  2919 00001976 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2920                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2921 0000197B 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2922 0000197D 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2923                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2924                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2925                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2926                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2927                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2928                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2929                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2930                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2931                              <1> 	;sub	edx, edx
  2932 00001980 66A1[7E670000]      <1> 	mov     ax, [fd0_type]
  2933 00001986 6621C0              <1> 	and     ax, ax
  2934 00001989 7473                <1> 	jz      short NON_DRV
  2935 0000198B FEC2                <1> 	inc     dl
  2936 0000198D 20E4                <1> 	and     ah, ah
  2937 0000198F 7402                <1> 	jz      short STO_DL
  2938 00001991 FEC2                <1> 	inc     dl
  2939                              <1> STO_DL:
  2940                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2941 00001993 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2942 00001996 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2943 0000199A 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2944                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2945 0000199C C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2946 000019A0 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2947                              <1> 	;;20/02/2015
  2948                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2949                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2950 000019A5 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2951 000019A7 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2952 000019AC 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2953                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2954 000019AE 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2955 000019B1 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2956 000019B4 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2957 000019B7 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2958                              <1> CHK_EST:
  2959 000019B9 8AA7[196D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2960 000019BF F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2961 000019C2 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2962                              <1> USE_EST:
  2963 000019C4 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2964 000019C7 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2965 000019CA 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2966                              <1> 
  2967                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2968                              <1> 
  2969 000019CC B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2970 000019CE E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2971 000019D3 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2972 000019D6 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2973 000019D9 F687[196D0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2974 000019E0 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2975                              <1> 
  2976                              <1> ;-----	IT IS 1.44 MB DRIVE
  2977                              <1> 
  2978                              <1> PARM144:
  2979 000019E2 B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2980 000019E4 E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2981 000019E9 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2982 000019EC 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2983                              <1> STO_CX:
  2984 000019EF 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2985                              <1> ES_DI:
  2986                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2987 000019F2 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2988                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2989                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2990                              <1> DP_OUT:
  2991 000019F5 E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2992                              <1> 	;XOR	AX,AX			; CLEAR
  2993                              <1> 	; 24/12/2021
  2994 000019FA 31C0                <1> 	xor	eax, eax
  2995 000019FC F8                  <1> 	CLC
  2996 000019FD C3                  <1> 	RETn
  2997                              <1> 
  2998                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2999                              <1> 
  3000                              <1> NON_DRV:
  3001                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  3002 000019FE 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  3003                              <1> NON_DRV1:
  3004 00001A01 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  3005 00001A06 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  3006                              <1> 
  3007                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  3008                              <1> 	
  3009 00001A08 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  3010                              <1> 	;MOV	AX,SI			; RESTORE AL
  3011 00001A0D 89F0                <1> 	mov	eax, esi ; 24/12/2021
  3012 00001A0F B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  3013 00001A11 F9                  <1> 	STC
  3014 00001A12 C3                  <1> 	RETn
  3015                              <1> 
  3016                              <1> NON_DRV2:
  3017                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  3018 00001A13 31C0                <1> 	xor	eax, eax	
  3019 00001A15 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  3020                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  3021 00001A19 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  3022                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  3023 00001A1C 89450C              <1> 	mov	[ebp+12], eax
  3024                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  3025 00001A1F EBD4                <1> 	JMP	SHORT DP_OUT
  3026                              <1> 
  3027                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3028                              <1> 
  3029                              <1> USE_EST2:
  3030 00001A21 B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3031 00001A23 E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3032 00001A28 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3033 00001A2B 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3034 00001A2E 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3035 00001A31 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3036 00001A33 EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3037                              <1> 
  3038                              <1> ;-------------------------------------------------------------------------------
  3039                              <1> ; DISK_TYPE (AH = 15H)	
  3040                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3041                              <1> ;
  3042                              <1> ;  ON ENTRY:	DI = DRIVE #
  3043                              <1> ;
  3044                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3045                              <1> ;-------------------------------------------------------------------------------
  3046                              <1> DSK_TYPE:
  3047 00001A35 E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3048 00001A3A 8A87[196D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3049 00001A40 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3050 00001A42 7415                <1> 	JZ	short NO_DRV
  3051 00001A44 B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3052 00001A46 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3053 00001A48 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3054 00001A4A B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3055                              <1> DT_BACK:
  3056                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3057 00001A4C 50                  <1> 	push	eax ; 24/12/2021
  3058 00001A4D E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3059                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3060 00001A52 58                  <1> 	pop	eax ; 24/12/2021
  3061 00001A53 F8                  <1> 	CLC				; NO ERROR
  3062                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3063                              <1> 	; 24/12/2021
  3064 00001A54 89F3                <1> 	mov	ebx, esi
  3065 00001A56 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3066 00001A58 C3                  <1> 	RETn
  3067                              <1> NO_DRV:	
  3068 00001A59 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3069 00001A5B EBEF                <1> 	JMP	SHORT DT_BACK
  3070                              <1> 
  3071                              <1> ;-------------------------------------------------------------------------------
  3072                              <1> ; DISK_CHANGE	(AH = 16H)
  3073                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3074                              <1> ;
  3075                              <1> ; ON ENTRY:	DI = DRIVE #
  3076                              <1> ;
  3077                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3078                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3079                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3080                              <1> ;-------------------------------------------------------------------------------
  3081                              <1> DSK_CHANGE:
  3082 00001A5D E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3083 00001A62 8A87[196D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3084 00001A68 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3085 00001A6A 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3086 00001A6C A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3087 00001A6E 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3088                              <1> DC0:
  3089 00001A70 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3090 00001A75 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3091                              <1> 
  3092 00001A77 C605[0C6D0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3093                              <1> 
  3094 00001A7E E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3095 00001A83 E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3096                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3097                              <1> 	; 24/12/2021
  3098 00001A88 89F3                <1> 	mov	ebx, esi
  3099 00001A8A 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3100 00001A8C C3                  <1> 	RETn
  3101                              <1> DC_NON:
  3102 00001A8D 800D[0C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3103 00001A94 EBE8                <1> 	JMP	SHORT FINIS
  3104                              <1> 
  3105                              <1> ;-------------------------------------------------------------------------------
  3106                              <1> ; FORMAT_SET	(AH = 17H)
  3107                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3108                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3109                              <1> ;
  3110                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3111                              <1> ;		DI     = DRIVE #
  3112                              <1> ;
  3113                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3114                              <1> ;		AH = @DSKETTE_STATUS
  3115                              <1> ;		CY = 1 IF ERROR
  3116                              <1> ;-------------------------------------------------------------------------------
  3117                              <1> FORMAT_SET:
  3118 00001A96 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3119                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3120                              <1> 	; 24/12/2021
  3121 00001A9B 56                  <1> 	push	esi
  3122 00001A9C 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3123 00001A9F 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3124 00001AA1 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3125 00001AA4 80A7[196D0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3126 00001AAB 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3127 00001AAD 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3128 00001AAF 808F[196D0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3129 00001AB6 EB48                <1> 	JMP	SHORT S0
  3130                              <1> NOT_320:
  3131 00001AB8 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3132 00001ABD 803D[0C6D0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3133 00001AC4 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3134                              <1> S3:
  3135 00001AC6 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3136 00001AC8 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3137 00001ACA 808F[196D0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3138 00001AD1 EB2D                <1> 	JMP	SHORT S0
  3139                              <1> NOT_320_12:
  3140 00001AD3 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3141 00001AD5 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3142 00001AD7 808F[196D0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3143 00001ADE EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3144                              <1> NOT_12:	
  3145 00001AE0 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3146 00001AE2 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3147                              <1> 
  3148 00001AE4 F687[196D0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3149 00001AEB 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3150 00001AED B050                <1> 	MOV	AL,MED_DET+RATE_300
  3151 00001AEF F687[196D0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3152 00001AF6 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3153                              <1> ASSUME:
  3154 00001AF8 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3155                              <1> OR_IT_IN:
  3156 00001AFA 0887[196D0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3157                              <1> S0:
  3158 00001B00 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3159 00001B05 E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3160                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3161                              <1> 	; 24/12/2021
  3162 00001B0A 5B                  <1> 	pop	ebx
  3163 00001B0B 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3164 00001B0D C3                  <1> 	RETn
  3165                              <1> FS_ERR:
  3166 00001B0E C605[0C6D0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3167 00001B15 EBE9                <1> 	JMP	SHORT S0
  3168                              <1> 
  3169                              <1> ;-------------------------------------------------------------------------------
  3170                              <1> ; SET_MEDIA	(AH = 18H)
  3171                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3172                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3173                              <1> ;
  3174                              <1> ; ON ENTRY:
  3175                              <1> ;	[BP]	= SECTOR PER TRACK
  3176                              <1> ;	[BP+1]	= TRACK #
  3177                              <1> ;	DI	= DRIVE #
  3178                              <1> ;
  3179                              <1> ; ON EXIT:
  3180                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3181                              <1> ;	IF NO ERROR:
  3182                              <1> ;		AH = 0
  3183                              <1> ;		CY = 0
  3184                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3185                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3186                              <1> ;	IF ERROR:	
  3187                              <1> ;		AH = @DSKETTE_STATUS
  3188                              <1> ;		CY = 1
  3189                              <1> ;-------------------------------------------------------------------------------
  3190                              <1> SET_MEDIA:
  3191 00001B17 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3192 00001B1C F687[196D0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3193 00001B23 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3194 00001B25 E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3195 00001B2A 803D[0C6D0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3196 00001B31 746B                <1> 	JE	short SM_RTN
  3197 00001B33 C605[0C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3198                              <1> SM_CMOS:
  3199 00001B3A E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3200                              <1> 	;;20/02/2015
  3201                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3202                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3203 00001B3F 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3204 00001B41 E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3205 00001B46 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3206 00001B48 57                  <1> 	PUSH	eDI			; SAVE REG.
  3207 00001B49 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3208 00001B4B B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3209                              <1> DR_SEARCH:
  3210 00001B50 8AA3[FC660000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3211 00001B56 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3212 00001B59 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3213 00001B5B 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3214                              <1> DR_FND:
  3215 00001B5D 8BBB[FD660000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3216                              <1> MD_SEARCH:
  3217 00001B63 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3218 00001B66 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3219 00001B69 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3220 00001B6B 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3221 00001B6E 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3222 00001B71 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3223                              <1> NXT_MD:
  3224                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3225 00001B73 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3226 00001B76 E2D8                <1> 	LOOP    DR_SEARCH
  3227 00001B78 5F                  <1> 	POP	eDI			; RESTORE REG.
  3228                              <1> MD_NOT_FND:
  3229 00001B79 C605[0C6D0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3230 00001B80 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3231                              <1> MD_FND:
  3232 00001B82 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3233 00001B85 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3234 00001B87 7502                <1> 	JNE	short MD_SET
  3235 00001B89 0C20                <1> 	OR	AL,DBL_STEP
  3236                              <1> MD_SET:
  3237                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3238 00001B8B 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3239 00001B8E 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3240 00001B90 5F                  <1> 	POP	eDI
  3241 00001B91 80A7[196D0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3242 00001B98 0887[196D0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3243                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3244                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3245                              <1> SM_RTN:
  3246 00001B9E E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3247 00001BA3 E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3248 00001BA8 C3                  <1> 	RETn
  3249                              <1> 
  3250                              <1> ;----------------------------------------------------------------
  3251                              <1> ; DR_TYPE_CHECK							:
  3252                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3253                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3254                              <1> ; ON ENTRY:							:
  3255                              <1> ;	AL = DRIVE TYPE						:
  3256                              <1> ; ON EXIT:							:
  3257                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3258                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3259                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3260                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3261                              <1> ; REGISTERS ALTERED: eBX						:
  3262                              <1> ;----------------------------------------------------------------		
  3263                              <1> DR_TYPE_CHECK:
  3264                              <1> 	;PUSH	AX			
  3265                              <1> 	; 24/12/2021
  3266 00001BA9 50                  <1> 	push	eax
  3267 00001BAA 51                  <1> 	PUSH	eCX
  3268 00001BAB 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3269 00001BAD B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3270                              <1> TYPE_CHK:	
  3271 00001BB2 8AA3[FC660000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3272 00001BB8 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3273 00001BBA 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3274                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3275 00001BBC 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3276 00001BBF E2F1                <1> 	LOOP    TYPE_CHK
  3277                              <1> 	;
  3278 00001BC1 BB[5B670000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3279                              <1> 					; Default for GET_PARM (11/12/2014)
  3280                              <1> 	;
  3281 00001BC6 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3282 00001BC7 EB06                <1> 	JMP	SHORT TYPE_RTN
  3283                              <1> DR_TYPE_VALID:
  3284 00001BC9 8B9B[FD660000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3285                              <1> TYPE_RTN:
  3286 00001BCF 59                  <1> 	POP	eCX
  3287                              <1> 	;POP	AX
  3288                              <1> 	; 24/12/2021
  3289 00001BD0 58                  <1> 	pop	eax
  3290 00001BD1 C3                  <1> 	RETn	
  3291                              <1> 		
  3292                              <1> ;----------------------------------------------------------------
  3293                              <1> ; SEND_SPEC							:
  3294                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3295                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3296                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3297                              <1> ; ON EXIT:	NONE						:	
  3298                              <1> ; REGISTERS ALTERED: CX, DX					:
  3299                              <1> ;----------------------------------------------------------------		
  3300                              <1> SEND_SPEC:
  3301 00001BD2 50                  <1> 	PUSH	eAX			; SAVE AX
  3302 00001BD3 B8[F91B0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3303 00001BD8 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3304 00001BD9 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3305 00001BDB E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3306 00001BE0 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3307 00001BE2 E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3308 00001BE7 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3309 00001BEC B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3310 00001BEE E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3311 00001BF3 E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3312 00001BF8 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3313                              <1> SPECBAC:
  3314 00001BF9 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3315 00001BFA C3                  <1> 	RETn
  3316                              <1> 
  3317                              <1> ;----------------------------------------------------------------
  3318                              <1> ; SEND_SPEC_MD							:
  3319                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3320                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3321                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3322                              <1> ; ON EXIT:	NONE						:	
  3323                              <1> ; REGISTERS ALTERED: AX						:
  3324                              <1> ;----------------------------------------------------------------		
  3325                              <1> SEND_SPEC_MD:
  3326 00001BFB 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3327 00001BFC B8[191C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3328 00001C01 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3329 00001C02 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3330 00001C04 E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3331 00001C09 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3332 00001C0B E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3333 00001C10 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3334 00001C13 E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3335 00001C18 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3336                              <1> SPEC_ESBAC:
  3337 00001C19 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3338 00001C1A C3                  <1> 	RETn
  3339                              <1> 
  3340                              <1> ;-------------------------------------------------------------------------------
  3341                              <1> ; XLAT_NEW  
  3342                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3343                              <1> ;	MODE TO NEW ARCHITECTURE.
  3344                              <1> ;
  3345                              <1> ; ON ENTRY:	DI = DRIVE #
  3346                              <1> ;-------------------------------------------------------------------------------
  3347                              <1> XLAT_NEW:
  3348 00001C1B 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3349 00001C1E 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3350 00001C20 80BF[196D0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3351 00001C27 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3352 00001C29 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3353 00001C2C C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3354 00001C2F A0[186D0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3355 00001C34 D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3356 00001C36 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3357 00001C38 80A7[196D0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3358 00001C3F 0887[196D0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3359                              <1> XN_OUT:
  3360 00001C45 C3                  <1> 	RETn
  3361                              <1> DO_DET:
  3362 00001C46 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3363 00001C4B C3                  <1> 	RETn
  3364                              <1> 
  3365                              <1> ;-------------------------------------------------------------------------------
  3366                              <1> ; XLAT_OLD 
  3367                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3368                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3369                              <1> ;
  3370                              <1> ; ON ENTRY:	DI = DRIVE
  3371                              <1> ;-------------------------------------------------------------------------------
  3372                              <1> XLAT_OLD:
  3373 00001C4C 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3374                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3375                              <1>         ;ja	XO_OUT
  3376                              <1>         ; 24/12/2021
  3377 00001C4F 77F4                <1> 	ja	short XN_OUT
  3378 00001C51 80BF[196D0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3379 00001C58 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3380                              <1> 
  3381                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3382                              <1> 
  3383 00001C5A 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3384 00001C5D C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3385 00001C60 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3386 00001C62 D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3387 00001C64 8425[186D0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3388 00001C6A 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3389                              <1> 
  3390                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3391                              <1> 
  3392 00001C6C B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3393 00001C6E D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3394 00001C70 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3395 00001C72 2025[186D0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3396                              <1> 
  3397                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3398                              <1> 
  3399 00001C78 8A87[196D0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3400 00001C7E 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3401 00001C80 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3402 00001C82 0805[186D0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3403                              <1> 
  3404                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3405                              <1> 
  3406                              <1> SAVE_SET:
  3407 00001C88 8AA7[196D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3408 00001C8E 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3409 00001C90 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3410 00001C93 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3411 00001C96 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3412 00001C98 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3413 00001C9A 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3414 00001C9D 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3415 00001C9F F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3416 00001CA2 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3417                              <1> UNKNO:
  3418 00001CA4 B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3419 00001CA6 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3420                              <1> CHK_144:
  3421 00001CA8 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3422                              <1> 	;;20/02/2015
  3423                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3424 00001CAD 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3425 00001CAF 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3426 00001CB1 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3427 00001CB3 B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3428 00001CB5 EB0C                <1> 	JMP	SHORT TST_DET
  3429                              <1> CHK_250:
  3430 00001CB7 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3431 00001CB9 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3432 00001CBC 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3433 00001CBE F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3434 00001CC1 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3435                              <1> TST_DET:
  3436 00001CC3 F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3437 00001CC6 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3438 00001CC8 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3439                              <1> AL_SET:
  3440 00001CCA 80A7[196D0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3441 00001CD1 0887[196D0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3442                              <1> XO_OUT:
  3443 00001CD7 C3                  <1> 	RETn
  3444                              <1> 
  3445                              <1> ;-------------------------------------------------------------------------------
  3446                              <1> ; RD_WR_VF
  3447                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3448                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3449                              <1> ;
  3450                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3451                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3452                              <1> ;
  3453                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3454                              <1> ;-------------------------------------------------------------------------------
  3455                              <1> RD_WR_VF:
  3456                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3457 00001CD8 50                  <1> 	push	eax ; 24/12/2021
  3458 00001CD9 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3459 00001CDE E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3460                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3461 00001CE3 58                  <1> 	pop	eax ; 24/12/2021
  3462                              <1> DO_AGAIN:
  3463                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3464 00001CE4 50                  <1> 	push	eax ; 24/12/2021
  3465 00001CE5 E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3466                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3467 00001CEA 58                  <1> 	pop	eax ; 24/12/2021
  3468                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3469                              <1> 	; 24/12/2021
  3470 00001CEB 7305                <1> 	jnc	short RWV
  3471 00001CED E9C3000000          <1> 	jmp	RWV_END
  3472                              <1> RWV:
  3473                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3474 00001CF2 50                  <1> 	push	eax ; 24/12/2021
  3475 00001CF3 8AB7[196D0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3476 00001CF9 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3477 00001CFC E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3478                              <1> 	;;20/02/2015
  3479                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3480 00001D01 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3481 00001D03 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3482 00001D05 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3483 00001D07 F687[196D0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3484 00001D0E 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3485 00001D10 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3486 00001D12 EB0F                <1> 	JMP	SHORT RWV_2
  3487                              <1> RWV_1:
  3488 00001D14 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3489 00001D16 F687[196D0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3490 00001D1D 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3491 00001D1F B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3492 00001D21 EB04                <1> 	jmp	short rwv_3
  3493                              <1> RWV_2:
  3494 00001D23 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3495 00001D25 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3496                              <1> rwv_3:
  3497 00001D27 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3498 00001D2C 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3499                              <1> 
  3500                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3501                              <1> 
  3502 00001D2E 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3503 00001D2F 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3504 00001D31 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3505                              <1> RWV_DR_SEARCH:
  3506 00001D36 8AA3[FC660000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3507 00001D3C 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3508 00001D3F 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3509 00001D41 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3510                              <1> RWV_DR_FND:
  3511 00001D43 8BBB[FD660000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3512                              <1> RWV_MD_SEARH:
  3513 00001D49 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3514 00001D4C 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3515                              <1> RWV_NXT_MD:
  3516                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3517 00001D4E 83C305              <1> 	add	eBX, 5
  3518 00001D51 E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3519 00001D53 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3520                              <1> 
  3521                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3522                              <1> 
  3523                              <1> RWV_ASSUME:
  3524 00001D54 BB[1A670000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3525 00001D59 F687[196D0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3526 00001D60 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3527 00001D62 BB[34670000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3528 00001D67 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3529                              <1> 
  3530                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3531                              <1> 	 			
  3532                              <1> RWV_MD_FND:
  3533 00001D69 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3534 00001D6B 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3535                              <1> 	
  3536                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3537                              <1> 
  3538                              <1> RWV_MD_FND1:
  3539 00001D6C E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3540 00001D71 E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3541 00001D76 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3542 00001D78 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3543                              <1> RWV_DBL:
  3544 00001D7D 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3545 00001D7E E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3546 00001D83 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3547 00001D84 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3548                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3549 00001D86 58                  <1> 	pop	eax ; 24/12/2021
  3550                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3551 00001D87 50                  <1> 	push	eax ; 24/12/2021
  3552 00001D88 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3553 00001D89 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3554 00001D8E 5B                  <1> 	POP	eBX 
  3555                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3556 00001D8F 58                  <1> 	pop	eax ; 24/12/2021
  3557 00001D90 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3558                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3559 00001D92 50                  <1> 	push	eax ; 24/12/2021
  3560 00001D93 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3561 00001D94 E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3562 00001D99 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3563 00001D9A 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3564 00001D9C E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3565 00001DA1 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3566 00001DA3 E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3567                              <1> CHK_RET:
  3568 00001DA8 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3569                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3570 00001DAD 58                  <1> 	pop	eax ; 24/12/2021
  3571 00001DAE 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3572 00001DB0 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3573                              <1> RWV_END:
  3574 00001DB5 E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3575 00001DBA E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3576                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3577                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3578 00001DBF 50                  <1> 	push	eax ; 24/12/2021
  3579 00001DC0 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3580                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3581 00001DC5 58                  <1> 	pop	eax ; 24/12/2021
  3582 00001DC6 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3583 00001DCB C3                  <1> 	RETn
  3584                              <1> 
  3585                              <1> ;-------------------------------------------------------------------------------
  3586                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3587                              <1> ;-------------------------------------------------------------------------------
  3588                              <1> SETUP_STATE:
  3589 00001DCC F687[196D0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3590 00001DD3 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3591 00001DD5 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3592 00001DD9 F687[196D0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3593 00001DE0 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3594 00001DE2 F687[196D0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3595 00001DE9 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3596 00001DEB 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3597                              <1> AX_SET:	
  3598 00001DEF 80A7[196D0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3599 00001DF6 08A7[196D0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3600 00001DFC 8025[146D0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3601 00001E03 C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3602 00001E06 0805[146D0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3603                              <1> J1C:	
  3604 00001E0C C3                  <1> 	RETn
  3605                              <1> 
  3606                              <1> ;-------------------------------------------------------------------------------
  3607                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3608                              <1> ;-------------------------------------------------------------------------------
  3609                              <1> FMT_INIT:
  3610 00001E0D F687[196D0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3611 00001E14 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3612 00001E16 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3613                              <1> 	;; 20/02/2015
  3614                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3615 00001E1B 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3616 00001E1D FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3617                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3618 00001E1F 8AA7[196D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3619 00001E25 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3620 00001E28 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3621 00001E2A 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3622 00001E2C 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3623 00001E2F EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3624                              <1> N_360:	
  3625 00001E31 FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3626 00001E33 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3627                              <1> F1_RATE:
  3628 00001E35 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3629 00001E38 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3630                              <1> N_12:	
  3631 00001E3A FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3632 00001E3C 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3633 00001E3E F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3634 00001E41 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3635 00001E43 F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3636 00001E46 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3637 00001E48 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3638 00001E4B EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3639                              <1> N_720:
  3640 00001E4D FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3641 00001E4F 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3642 00001E51 EBE2                <1> 	JMP	SHORT F1_RATE
  3643                              <1> ISNT_12: 
  3644 00001E53 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3645                              <1> 
  3646                              <1> SKP_STATE:
  3647 00001E56 88A7[196D0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3648                              <1> F1_OUT:
  3649 00001E5C C3                  <1> 	RETn
  3650                              <1> CL_DRV:	
  3651 00001E5D 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3652 00001E5F EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3653                              <1> 
  3654                              <1> ;-------------------------------------------------------------------------------
  3655                              <1> ; MED_CHANGE	
  3656                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3657                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3658                              <1> ;
  3659                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3660                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3661                              <1> ;-------------------------------------------------------------------------------
  3662                              <1> MED_CHANGE:
  3663 00001E61 E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3664 00001E66 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3665 00001E68 80A7[196D0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3666                              <1> 
  3667                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3668                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3669                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3670                              <1> 
  3671 00001E6F 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3672 00001E72 B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3673 00001E74 D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3674 00001E76 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3675 00001E78 FA                  <1> 	CLI				; NO INTERRUPTS
  3676 00001E79 2005[0A6D0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3677 00001E7F FB                  <1> 	STI				; INTERRUPTS ENABLED
  3678 00001E80 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3679                              <1> 
  3680                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3681                              <1> 
  3682 00001E85 E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3683 00001E8A B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3684 00001E8C E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3685 00001E91 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3686 00001E93 E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3687 00001E98 C605[0C6D0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3688                              <1> OK1:
  3689 00001E9F E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3690 00001EA4 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3691                              <1> OK4:
  3692 00001EA6 C605[0C6D0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3693                              <1> OK2:		
  3694 00001EAD F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3695 00001EAE C3                  <1> 	RETn
  3696                              <1> MC_OUT:
  3697 00001EAF F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3698 00001EB0 C3                  <1> 	RETn
  3699                              <1> 
  3700                              <1> ;-------------------------------------------------------------------------------
  3701                              <1> ; SEND_RATE
  3702                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3703                              <1> ; ON ENTRY:	DI = DRIVE #
  3704                              <1> ; ON EXIT:	NONE
  3705                              <1> ; REGISTERS ALTERED: DX
  3706                              <1> ;-------------------------------------------------------------------------------
  3707                              <1> SEND_RATE:
  3708                              <1> 	;PUSH	AX			; SAVE REG.
  3709                              <1> 	; 24/12/2021
  3710 00001EB1 50                  <1> 	push	eax
  3711 00001EB2 8025[146D0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3712 00001EB9 8A87[196D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3713 00001EBF 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3714 00001EC1 0805[146D0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3715 00001EC7 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3716 00001ECA 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3717 00001ECE EE                  <1> 	OUT	DX,AL
  3718                              <1> 	;POP	AX			; RESTORE REG.
  3719                              <1> 	; 24/12/2021
  3720 00001ECF 58                  <1> 	pop	eax
  3721 00001ED0 C3                  <1> 	RETn
  3722                              <1> 
  3723                              <1> ;-------------------------------------------------------------------------------
  3724                              <1> ; CHK_LASTRATE
  3725                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3726                              <1> ; ON ENTRY:
  3727                              <1> ;	DI = DRIVE #
  3728                              <1> ; ON EXIT:
  3729                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3730                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3731                              <1> ; REGISTERS ALTERED: DX
  3732                              <1> ;-------------------------------------------------------------------------------
  3733                              <1> CHK_LASTRATE:
  3734                              <1> 	;PUSH	AX			; SAVE REG.
  3735                              <1> 	; 24/12/2021
  3736 00001ED1 50                  <1> 	push	eax
  3737 00001ED2 2225[146D0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3738 00001ED8 8A87[196D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3739 00001EDE 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3740 00001EE2 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3741                              <1> 					; ZF = 1 RATE IS THE SAME
  3742                              <1> 	;POP	AX			; RESTORE REG.
  3743                              <1> 	; 24/12/2021
  3744 00001EE4 58                  <1> 	pop	eax
  3745 00001EE5 C3                  <1> 	RETn
  3746                              <1> 
  3747                              <1> ;-------------------------------------------------------------------------------
  3748                              <1> ; DMA_SETUP
  3749                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3750                              <1> ;
  3751                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3752                              <1> ;
  3753                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3754                              <1> ;-------------------------------------------------------------------------------
  3755                              <1> 
  3756                              <1> ; SI = Head #, # of Sectors or DASD Type
  3757                              <1> 
  3758                              <1> ; 22/08/2015
  3759                              <1> ; 08/02/2015 - Protected Mode Modification
  3760                              <1> ; 06/02/2015 - 07/02/2015
  3761                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3762                              <1> ; (DMA Addres = Physical Address)
  3763                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3764                              <1> ;
  3765                              <1> ; 04/02/2016 (clc)
  3766                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3767                              <1> ; 16/12/2014 (IODELAY)
  3768                              <1> 
  3769                              <1> DMA_SETUP:
  3770                              <1> 
  3771                              <1> ;; 20/02/2015
  3772 00001EE6 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3773 00001EE9 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3774 00001EEF 7569                <1> 	jnz	short dma_bnd_err_stc
  3775                              <1> 	;
  3776                              <1> 	;push	ax			; DMA command
  3777                              <1> 	; 24/12/2021
  3778 00001EF1 50                  <1> 	push	eax
  3779 00001EF2 52                  <1> 	push	edx			; *
  3780 00001EF3 B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3781 00001EF5 E840030000          <1> 	call	GET_PARM		; 
  3782 00001EFA 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3783                              <1> 	;mov	ax, si			; Sector count
  3784                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3785                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3786                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3787                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3788                              <1> 	; 24/12/2021
  3789 00001EFC 89F2                <1> 	mov	edx, esi
  3790 00001EFE 29C0                <1> 	sub	eax, eax
  3791 00001F00 88D4                <1> 	mov	ah, dl
  3792 00001F02 D1E8                <1> 	shr	eax, 1
  3793 00001F04 D3E0                <1> 	shl	eax, cl
  3794                              <1> 	;
  3795 00001F06 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3796 00001F08 6689C1              <1> 	mov	cx, ax
  3797 00001F0B 5A                  <1> 	pop	edx			; *
  3798                              <1> 	;pop	ax
  3799                              <1> 	; 24/12/2021
  3800 00001F0C 58                  <1> 	pop	eax
  3801 00001F0D 3C42                <1> 	cmp	al, 42h
  3802 00001F0F 7507                <1>         jne     short NOT_VERF
  3803 00001F11 BA0000FF00          <1> 	mov	edx, 0FF0000h
  3804 00001F16 EB08                <1> 	jmp	short J33
  3805                              <1> NOT_VERF:
  3806 00001F18 6601CA              <1> 	add	dx, cx			; check for overflow
  3807 00001F1B 723E                <1> 	jc	short dma_bnd_err
  3808                              <1> 	;
  3809 00001F1D 6629CA              <1> 	sub	dx, cx			; Restore start address
  3810                              <1> J33:
  3811 00001F20 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3812 00001F21 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3813                              <1> 	IODELAY				; WAIT FOR I/O
  2155 00001F23 EB00                <2>  jmp short $+2
  2156 00001F25 EB00                <2>  jmp short $+2
  3814 00001F27 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3815 00001F29 89D0                <1> 	mov	eax,edx			; Buffer address
  3816 00001F2B E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3817                              <1> 	IODELAY				; WAIT FOR I/O
  2155 00001F2D EB00                <2>  jmp short $+2
  2156 00001F2F EB00                <2>  jmp short $+2
  3818 00001F31 88E0                <1> 	MOV	AL,AH
  3819 00001F33 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3820 00001F35 C1E810              <1> 	shr	eax,16
  3821                              <1> 	IODELAY				; I/O WAIT STATE
  2155 00001F38 EB00                <2>  jmp short $+2
  2156 00001F3A EB00                <2>  jmp short $+2
  3822 00001F3C E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3823                              <1> 	IODELAY
  2155 00001F3E EB00                <2>  jmp short $+2
  2156 00001F40 EB00                <2>  jmp short $+2
  3824 00001F42 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3825 00001F45 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3826                              <1> 	IODELAY				; WAIT FOR I/O
  2155 00001F47 EB00                <2>  jmp short $+2
  2156 00001F49 EB00                <2>  jmp short $+2
  3827 00001F4B 88E0                <1> 	MOV	AL,AH
  3828 00001F4D E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3829                              <1> 	IODELAY
  2155 00001F4F EB00                <2>  jmp short $+2
  2156 00001F51 EB00                <2>  jmp short $+2
  3830 00001F53 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3831 00001F54 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3832 00001F56 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3833                              <1> 
  3834 00001F58 F8                  <1> 	clc	; 04/02/2016
  3835 00001F59 C3                  <1> 	retn
  3836                              <1> 
  3837                              <1> dma_bnd_err_stc:
  3838 00001F5A F9                  <1> 	stc
  3839                              <1> dma_bnd_err:
  3840 00001F5B C605[0C6D0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3841 00001F62 C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3842                              <1> 
  3843                              <1> ;; 16/12/2014
  3844                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3845                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3846                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3847                              <1> ;;	IODELAY
  3848                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3849                              <1> ;;	;SIODELAY
  3850                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3851                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3852                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3853                              <1> ;;      ;JMP	SHORT J33
  3854                              <1> ;;;NOT_VERF:	
  3855                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3856                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3857                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3858                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3859                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3860                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3861                              <1> ;;	;JNC	short J33
  3862                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3863                              <1> ;;;J33:
  3864                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3865                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3866                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3867                              <1> ;;	IODELAY
  3868                              <1> ;;	MOV	AL,AH
  3869                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3870                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3871                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3872                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3873                              <1> ;;	IODELAY
  3874                              <1> ;;	;AND	AL,00001111B
  3875                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3876                              <1> ;;	;SIODELAY
  3877                              <1> ;;
  3878                              <1> ;;;----- DETERMINE COUNT
  3879                              <1> ;;	sub	eax, eax ; 08/02/2015
  3880                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3881                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3882                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3883                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3884                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3885                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3886                              <1> ;;	CALL	GET_PARM		; "
  3887                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3888                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3889                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3890                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3891                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3892                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3893                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3894                              <1> ;;	IODELAY
  3895                              <1> ;;	MOV	AL, AH
  3896                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3897                              <1> ;;	;IODELAY
  3898                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3899                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3900                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3901                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3902                              <1> ;;	add	ecx, eax ; 08/02/2015
  3903                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3904                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3905                              <1> ;;	SIODELAY
  3906                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3907                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3908                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3909                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3910                              <1> ;;	jz	short NO_BAD
  3911                              <1> ;;dma_bnd_err:
  3912                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3913                              <1> ;;NO_BAD:
  3914                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3915                              <1> 
  3916                              <1> ;-------------------------------------------------------------------------------
  3917                              <1> ; FMTDMA_SET
  3918                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3919                              <1> ;
  3920                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3921                              <1> ;
  3922                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3923                              <1> ;-------------------------------------------------------------------------------
  3924                              <1> 
  3925                              <1> 	; 24/12/2021
  3926                              <1> FMTDMA_SET:
  3927                              <1> ;; 20/02/2015 modification	
  3928 00001F63 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3929 00001F66 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3930 00001F6C 75EC                <1> 	jnz	short dma_bnd_err_stc
  3931                              <1> 	;
  3932                              <1> 	;push	dx			; *
  3933                              <1> 	; 24/12/2021
  3934 00001F6E 52                  <1> 	push	edx
  3935 00001F6F B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3936 00001F71 E8C4020000          <1> 	call	GET_PARM		; "
  3937                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3938                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3939                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3940                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3941                              <1> 	;mov	cx, ax
  3942                              <1> 	; 24/12/2021
  3943 00001F76 29C9                <1> 	sub	ecx, ecx
  3944 00001F78 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3945 00001F7A D1E1                <1> 	shl	ecx, 1
  3946 00001F7C D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3947 00001F7E 6649                <1> 	dec	cx
  3948                              <1> 	;pop	dx			; *
  3949                              <1> 	; 24/12/2021
  3950 00001F80 5A                  <1> 	pop	edx
  3951 00001F81 6601CA              <1> 	add	dx, cx			; check for overflow
  3952 00001F84 72D5                <1> 	jc	short dma_bnd_err
  3953                              <1> 	;
  3954 00001F86 6629CA              <1> 	sub	dx, cx			; Restore start address
  3955                              <1> 	;
  3956 00001F89 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3957 00001F8B FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3958 00001F8C E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3959                              <1> 	IODELAY				; WAIT FOR I/O
  2155 00001F8E EB00                <2>  jmp short $+2
  2156 00001F90 EB00                <2>  jmp short $+2
  3960 00001F92 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3961 00001F94 89D0                <1> 	mov	eax,edx			; Buffer address
  3962 00001F96 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3963                              <1> 	IODELAY				; WAIT FOR I/O
  2155 00001F98 EB00                <2>  jmp short $+2
  2156 00001F9A EB00                <2>  jmp short $+2
  3964 00001F9C 88E0                <1> 	MOV	AL,AH
  3965 00001F9E E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3966 00001FA0 C1E810              <1> 	shr	eax,16
  3967                              <1> 	IODELAY				; I/O WAIT STATE
  2155 00001FA3 EB00                <2>  jmp short $+2
  2156 00001FA5 EB00                <2>  jmp short $+2
  3968 00001FA7 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3969                              <1> 	IODELAY
  2155 00001FA9 EB00                <2>  jmp short $+2
  2156 00001FAB EB00                <2>  jmp short $+2
  3970 00001FAD 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3971 00001FB0 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3972                              <1> 	IODELAY				; WAIT FOR I/O
  2155 00001FB2 EB00                <2>  jmp short $+2
  2156 00001FB4 EB00                <2>  jmp short $+2
  3973 00001FB6 88E0                <1> 	MOV	AL,AH
  3974 00001FB8 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3975                              <1> 	IODELAY
  2155 00001FBA EB00                <2>  jmp short $+2
  2156 00001FBC EB00                <2>  jmp short $+2
  3976 00001FBE FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3977 00001FBF B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3978 00001FC1 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3979 00001FC3 C3                  <1> 	retn
  3980                              <1> 
  3981                              <1> ;; 08/02/2015 - Protected Mode Modification
  3982                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3983                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3984                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3985                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3986                              <1> ;;	IODELAY
  3987                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3988                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3989                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3990                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3991                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3992                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3993                              <1> ;;	;JNC	short J33A
  3994                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3995                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3996                              <1> ;;;J33A:
  3997                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3998                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3999                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4000                              <1> ;;	IODELAY
  4001                              <1> ;;	MOV	AL,AH
  4002                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  4003                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  4004                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  4005                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  4006                              <1> ;;	IODELAY
  4007                              <1> ;;	;AND	AL,00001111B
  4008                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  4009                              <1> ;;
  4010                              <1> ;;;----- DETERMINE COUNT
  4011                              <1> ;;	sub	eax, eax ; 08/02/2015
  4012                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  4013                              <1> ;;	CALL	GET_PARM		; "
  4014                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  4015                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  4016                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  4017                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  4018                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  4019                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  4020                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4021                              <1> ;;	IODELAY
  4022                              <1> ;;	MOV	AL, AH
  4023                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  4024                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  4025                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4026                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4027                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4028                              <1> ;;	add	ecx, eax ; 08/02/2015
  4029                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4030                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4031                              <1> ;;	SIODELAY
  4032                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4033                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4034                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4035                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4036                              <1> ;;	jz	short FMTDMA_OK
  4037                              <1> ;;	stc	; 20/02/2015
  4038                              <1> ;;fmtdma_bnd_err:
  4039                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4040                              <1> ;;FMTDMA_OK:
  4041                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4042                              <1> 
  4043                              <1> ;-------------------------------------------------------------------------------
  4044                              <1> ; NEC_INIT	
  4045                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4046                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4047                              <1> ;
  4048                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4049                              <1> ;
  4050                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4051                              <1> ;-------------------------------------------------------------------------------
  4052                              <1> NEC_INIT:
  4053                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4054                              <1> 	; 24/12/2021
  4055 00001FC4 50                  <1> 	push	eax
  4056 00001FC5 E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4057                              <1> 
  4058                              <1> ;-----	DO THE SEEK OPERATION
  4059                              <1> 
  4060 00001FCA 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4061 00001FCD E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4062                              <1> 	;POP	AX			; RECOVER COMMAND
  4063                              <1> 	; 24/12/2021
  4064 00001FD2 58                  <1> 	pop	eax
  4065 00001FD3 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4066 00001FD5 BB[F31F0000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4067 00001FDA 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4068                              <1> 
  4069                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4070                              <1> 
  4071 00001FDB E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4072 00001FE0 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4073 00001FE3 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4074 00001FE5 C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4075 00001FE8 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4076 00001FEB 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4077 00001FED E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4078 00001FF2 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4079                              <1> ER_1:
  4080 00001FF3 C3                  <1> 	RETn
  4081                              <1> 
  4082                              <1> ;-------------------------------------------------------------------------------
  4083                              <1> ; RWV_COM
  4084                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4085                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4086                              <1> ;
  4087                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4088                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4089                              <1> ;-------------------------------------------------------------------------------
  4090                              <1> RWV_COM:
  4091 00001FF4 B8[3F200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4092 00001FF9 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4093 00001FFA 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4094 00001FFD E83E030000          <1> 	CALL	NEC_OUTPUT
  4095 00002002 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4096 00002005 E836030000          <1> 	CALL	NEC_OUTPUT
  4097 0000200A 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4098 0000200D E82E030000          <1> 	CALL	NEC_OUTPUT
  4099 00002012 B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4100 00002014 E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4101 00002019 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4102 0000201E B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4103 00002020 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4104 00002025 E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4105 0000202A 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4106                              <1> _R15:
  4107 0000202D E80E030000          <1> 	CALL	NEC_OUTPUT
  4108 00002032 B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4109 00002034 E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4110 00002039 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4111 0000203E 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4112                              <1> ER_2:
  4113 0000203F C3                  <1> 	RETn
  4114                              <1> 
  4115                              <1> ;-------------------------------------------------------------------------------
  4116                              <1> ; NEC_TERM
  4117                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4118                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4119                              <1> ;
  4120                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4121                              <1> ;-------------------------------------------------------------------------------
  4122                              <1> NEC_TERM:
  4123                              <1> 
  4124                              <1> ;-----	LET THE OPERATION HAPPEN
  4125                              <1> 
  4126 00002040 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4127 00002041 E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4128 00002046 9C                  <1> 	PUSHFd	; 24/12/2021
  4129 00002047 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4130 0000204C 724B                <1> 	JC	short SET_END_POP
  4131 0000204E 9D                  <1> 	POPFd	; 24/12/2021
  4132 0000204F 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4133                              <1> 
  4134                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4135                              <1> 
  4136 00002051 FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4137 00002052 BE[0D6D0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4138 00002057 AC                  <1> 	lodsb				; GET ST0
  4139 00002058 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4140 0000205A 7433                <1> 	JZ	short SET_END
  4141 0000205C 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4142 0000205E 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4143                              <1> 
  4144                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4145                              <1> 
  4146 00002060 AC                  <1> 	lodsb				; GET ST1
  4147 00002061 D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4148 00002063 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4149 00002065 7222                <1> 	JC	short J19
  4150 00002067 C0E002              <1> 	SAL	AL,2
  4151 0000206A B410                <1> 	MOV	AH,BAD_CRC
  4152 0000206C 721B                <1> 	JC	short J19
  4153 0000206E D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4154 00002070 B408                <1> 	MOV	AH,BAD_DMA
  4155 00002072 7215                <1> 	JC	short J19
  4156 00002074 C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4157 00002077 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4158 00002079 720E                <1> 	JC	short J19
  4159 0000207B D0E0                <1> 	SAL	AL,1
  4160 0000207D B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4161 0000207F 7208                <1> 	JC	short J19
  4162 00002081 D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4163 00002083 B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4164 00002085 7202                <1> 	JC	short J19
  4165                              <1> 
  4166                              <1> ;----- 	NEC MUST HAVE FAILED
  4167                              <1> J18:
  4168 00002087 B420                <1> 	MOV	AH,BAD_NEC
  4169                              <1> J19:
  4170 00002089 0825[0C6D0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4171                              <1> SET_END:
  4172 0000208F 803D[0C6D0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4173 00002096 F5                  <1> 	CMC
  4174 00002097 5E                  <1> 	POP	eSI
  4175 00002098 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4176                              <1> 
  4177                              <1> SET_END_POP:
  4178 00002099 9D                  <1> 	POPFd	; 24/12/2021
  4179 0000209A EBF3                <1> 	JMP	SHORT SET_END
  4180                              <1> 
  4181                              <1> ;-------------------------------------------------------------------------------
  4182                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4183                              <1> ;-------------------------------------------------------------------------------
  4184                              <1> DSTATE:
  4185 0000209C 803D[0C6D0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4186 000020A3 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4187 000020A5 808F[196D0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4188 000020AC F687[196D0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4189 000020B3 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4190 000020B5 8A87[196D0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4191 000020BB 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4192 000020BD 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4193 000020BF 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4194                              <1> 
  4195                              <1> ;----- 	CHECK IF IT IS 1.44M
  4196                              <1> 
  4197 000020C1 E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4198                              <1> 	;;20/02/2015
  4199                              <1> 	;;JC	short M_12		; CMOS BAD
  4200 000020C6 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4201 000020C8 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4202 000020CA 7410                <1> 	JE	short M_12		; YES
  4203                              <1> M_720:
  4204 000020CC 80A7[196D0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4205 000020D3 808F[196D0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4206 000020DA EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4207                              <1> M_12:	
  4208 000020DC 808F[196D0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4209                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4210                              <1> SETBAC:
  4211 000020E3 C3                  <1> 	RETn
  4212                              <1> 
  4213                              <1> ;-------------------------------------------------------------------------------
  4214                              <1> ; RETRY	
  4215                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4216                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4217                              <1> ;
  4218                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4219                              <1> ;-------------------------------------------------------------------------------
  4220                              <1> RETRY:
  4221 000020E4 803D[0C6D0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4222 000020EB 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4223 000020ED 803D[0C6D0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4224 000020F4 743C                <1> 	JZ	short NO_RETRY
  4225 000020F6 8AA7[196D0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4226 000020FC F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4227 000020FF 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4228 00002101 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4229 00002104 8A2D[146D0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4230 0000210A C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4231 0000210D 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4232 00002110 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4233 00002112 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4234                              <1> 
  4235                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4236                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4237                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4238                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4239                              <1> 
  4240 00002114 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4241 00002117 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4242 00002119 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4243 0000211C 80A7[196D0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4244                              <1> 					; RATE, DBL STEP OFF
  4245 00002123 08A7[196D0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4246 00002129 C605[0C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4247 00002130 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4248 00002131 C3                  <1> 	RETn				; RETRY RETURN
  4249                              <1> 
  4250                              <1> NO_RETRY:
  4251 00002132 F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4252 00002133 C3                  <1> 	RETn				; NO RETRY RETURN
  4253                              <1> 
  4254                              <1> ;-------------------------------------------------------------------------------
  4255                              <1> ; NUM_TRANS
  4256                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4257                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4258                              <1> ;
  4259                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4260                              <1> ;		SI-HI  = HEAD
  4261                              <1> ;		[BP]   = START SECTOR
  4262                              <1> ;
  4263                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4264                              <1> ;-------------------------------------------------------------------------------
  4265                              <1> NUM_TRANS:
  4266 00002134 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4267 00002136 803D[0C6D0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4268                              <1> 	; 24/12/2021
  4269 0000213D 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4270 0000213F B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4271 00002141 E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4272 00002146 8A1D[126D0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4273 0000214C 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4274 0000214F 3A2D[116D0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4275 00002155 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4276 00002157 8A2D[106D0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4277 0000215D 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4278 00002160 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4279 00002162 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4280                              <1> DIF_HD:
  4281 00002164 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4282                              <1> SAME_TRK:
  4283 00002166 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4284 00002169 88D8                <1> 	MOV	AL,BL			; TO AL
  4285                              <1> NT_OUT:
  4286 0000216B C3                  <1> 	RETn
  4287                              <1> 
  4288                              <1> ;-------------------------------------------------------------------------------
  4289                              <1> ; SETUP_END
  4290                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4291                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4292                              <1> ;
  4293                              <1> ; ON EXIT:
  4294                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4295                              <1> ;-------------------------------------------------------------------------------
  4296                              <1> SETUP_END:
  4297 0000216C B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4298                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4299 0000216E 50                  <1> 	push	eax ; 24/12/2021
  4300 0000216F E8C6000000          <1> 	CALL	GET_PARM
  4301 00002174 8825[0B6D0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4302                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4303 0000217A 58                  <1> 	pop	eax ; 24/12/2021
  4304 0000217B 8A25[0C6D0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4305 00002181 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4306 00002183 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4307 00002185 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4308                              <1> NUN_ERR: 
  4309 00002187 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4310 0000218A F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4311 0000218B C3                  <1> 	RETn
  4312                              <1> 
  4313                              <1> ;-------------------------------------------------------------------------------
  4314                              <1> ; SETUP_DBL
  4315                              <1> ;	CHECK DOUBLE STEP.
  4316                              <1> ;
  4317                              <1> ; ON ENTRY :	DI = DRIVE
  4318                              <1> ;
  4319                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4320                              <1> ;-------------------------------------------------------------------------------
  4321                              <1> SETUP_DBL:
  4322 0000218C 8AA7[196D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4323 00002192 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4324 00002195 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4325                              <1> 
  4326                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4327                              <1> 
  4328 00002197 C605[096D0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4329 0000219E E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4330 000021A3 B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4331 000021A5 E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4332 000021AA E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4333 000021AF 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4334                              <1> 
  4335                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4336                              <1> 
  4337 000021B1 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4338 000021B5 F687[196D0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4339 000021BC 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4340 000021BE B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4341                              <1> 
  4342                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4343                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4344                              <1> ;	THEN SET DOUBLE STEP ON.
  4345                              <1> 
  4346                              <1> CNT_OK:
  4347 000021C0 C605[0B6D0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4348                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4349                              <1> 	; 24/12/2021
  4350 000021C7 51                  <1> 	push	ecx
  4351 000021C8 C605[0C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4352 000021CF 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4353 000021D2 D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4354 000021D4 C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4355                              <1> 	;PUSH	AX			; SAVE HEAD
  4356                              <1> 	; 24/12/2021
  4357 000021D7 50                  <1> 	push	eax
  4358 000021D8 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4359                              <1> 	;POP	AX			; RESTORE HEAD
  4360                              <1> 	; 24/12/2021
  4361 000021DD 58                  <1> 	pop	eax
  4362 000021DE 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4363 000021E1 E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4364 000021E6 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4365 000021E7 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4366 000021EC 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4367                              <1> 	;POP	CX			; RESTORE COUNT
  4368                              <1> 	; 24/12/2021
  4369 000021ED 59                  <1> 	pop	ecx
  4370 000021EE 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4371 000021F0 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4372 000021F2 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4373 000021F4 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4374                              <1> 
  4375                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4376                              <1> 
  4377                              <1> SD_ERR:	
  4378 000021F6 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4379 000021F7 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4380                              <1> 
  4381                              <1> DO_CHK:
  4382 000021F8 8A0D[106D0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4383 000021FE 888F[1D6D0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4384 00002204 D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4385 00002206 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4386 00002208 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4387 0000220A 808F[196D0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4388                              <1> NO_DBL:
  4389 00002211 F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4390 00002212 C3                  <1> 	RETn
  4391                              <1> 
  4392                              <1> ;-------------------------------------------------------------------------------
  4393                              <1> ; READ_ID
  4394                              <1> ;	READ ID FUNCTION.
  4395                              <1> ;
  4396                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4397                              <1> ;
  4398                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4399                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4400                              <1> ;-------------------------------------------------------------------------------
  4401                              <1> READ_ID:
  4402 00002213 B8[30220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4403 00002218 50                  <1> 	PUSH	eAX
  4404 00002219 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4405 0000221B E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4406 00002220 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4407 00002223 88C4                <1> 	MOV	AH,AL
  4408 00002225 E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4409 0000222A E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4410 0000222F 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4411                              <1> ER_3:
  4412 00002230 C3                  <1> 	RETn
  4413                              <1> 
  4414                              <1> ;-------------------------------------------------------------------------------
  4415                              <1> ; CMOS_TYPE
  4416                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4417                              <1> ;
  4418                              <1> ; ON ENTRY:	DI = DRIVE #
  4419                              <1> ;
  4420                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4421                              <1> ;-------------------------------------------------------------------------------
  4422                              <1> 
  4423                              <1> CMOS_TYPE: ; 11/12/2014
  4424 00002231 8A87[7E670000]      <1> 	mov	al, [eDI+fd0_type]
  4425 00002237 20C0                <1> 	and 	al, al ; 18/12/2014
  4426 00002239 C3                  <1> 	retn
  4427                              <1> 
  4428                              <1> ;CMOS_TYPE:
  4429                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4430                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4431                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4432                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4433                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4434                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4435                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4436                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4437                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4438                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4439                              <1> ;TB:
  4440                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4441                              <1> ;BAD_CM:
  4442                              <1> ;	RETn				; CY, STATUS OF READ
  4443                              <1> 
  4444                              <1> ;-------------------------------------------------------------------------------
  4445                              <1> ; GET_PARM
  4446                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4447                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4448                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4449                              <1> ;	THE PARAMETER IN DL.
  4450                              <1> ;
  4451                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4452                              <1> ;
  4453                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4454                              <1> ;		AL,DH DESTROYED
  4455                              <1> ;-------------------------------------------------------------------------------
  4456                              <1> GET_PARM:
  4457                              <1> 	;PUSH	DS
  4458 0000223A 56                  <1> 	PUSH	eSI
  4459                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4460                              <1>     	;MOV	DS,AX
  4461                              <1> 	;;mov	ax, cs
  4462                              <1> 	;;mov	ds, ax
  4463                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4464 0000223B 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4465                              <1> 	;SUB	BH,BH			; BX = INDEX
  4466 0000223D 81E3FF000000        <1> 	and	ebx, 0FFh
  4467                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4468                              <1> 	;
  4469                              <1> 	; 17/12/2014
  4470 00002243 66A1[71670000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4471 00002249 38E0                <1> 	cmp	al, ah
  4472 0000224B 7425                <1> 	je	short gpndc
  4473 0000224D A2[72670000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4474 00002252 53                  <1> 	push	ebx ; 08/02/2015
  4475 00002253 88C3                <1> 	mov	bl, al 
  4476                              <1> 	; 11/12/2014
  4477 00002255 8A83[7E670000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4478                              <1> 	; 18/12/2014
  4479 0000225B 20C0                <1> 	and	al, al
  4480 0000225D 7507                <1> 	jnz	short gpdtc
  4481 0000225F BB[5B670000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4482 00002264 EB05                <1>         jmp     short gpdpu
  4483                              <1> gpdtc:	
  4484 00002266 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4485                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4486                              <1> gpdpu:
  4487 0000226B 891D[F8660000]      <1> 	mov	[DISK_POINTER], ebx
  4488 00002271 5B                  <1> 	pop	ebx
  4489                              <1> gpndc:
  4490 00002272 8B35[F8660000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4491 00002278 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4492 0000227B 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4493 0000227D 5E                  <1> 	POP	eSI
  4494                              <1> 	;POP	DS
  4495 0000227E C3                  <1> 	RETn
  4496                              <1> 
  4497                              <1> ;-------------------------------------------------------------------------------
  4498                              <1> ; MOTOR_ON
  4499                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4500                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4501                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4502                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4503                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4504                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4505                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4506                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4507                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4508                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4509                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4510                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4511                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4512                              <1> ;
  4513                              <1> ; ON ENTRY:	DI = DRIVE #
  4514                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4515                              <1> ;-------------------------------------------------------------------------------
  4516                              <1> MOTOR_ON:
  4517 0000227F 53                  <1> 	PUSH	eBX			; SAVE REG.
  4518 00002280 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4519 00002285 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4520 00002287 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4521 0000228C E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4522                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4523                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4524                              <1> M_WAIT:
  4525 00002291 B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4526 00002293 E8A2FFFFFF          <1> 	CALL	GET_PARM
  4527                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4528                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4529                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4530 00002298 80FC08              <1> 	cmp	ah, 8
  4531                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4532 0000229B 7702                <1> 	ja	short J13
  4533                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4534 0000229D B408                <1> 	mov	ah, 8
  4535                              <1> 
  4536                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4537                              <1> GP2:	
  4538                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4539                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4540 0000229F B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4541 000022A4 E80FF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4542                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4543 000022A9 FECC                <1> 	dec	ah
  4544 000022AB 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4545                              <1> MOT_IS_ON:
  4546 000022AD 5B                  <1> 	POP	eBX			; RESTORE REG.
  4547 000022AE C3                  <1> 	RETn
  4548                              <1> 
  4549                              <1> ;-------------------------------------------------------------------------------
  4550                              <1> ; TURN_ON
  4551                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4552                              <1> ;
  4553                              <1> ; ON ENTRY:	DI = DRIVE #
  4554                              <1> ;
  4555                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4556                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4557                              <1> ;		AX,BX,CX,DX DESTROYED
  4558                              <1> ;-------------------------------------------------------------------------------
  4559                              <1> TURN_ON:
  4560 000022AF 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4561 000022B1 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4562 000022B3 C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4563 000022B6 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4564 000022B7 C605[0B6D0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4565 000022BE A0[0A6D0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4566 000022C3 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4567 000022C5 B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4568 000022C7 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4569                              <1> 
  4570                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4571                              <1> ;  BL = DRIVE SELECT DESIRED
  4572                              <1> ;  AH = MOTOR ON MASK DESIRED
  4573                              <1> 
  4574 000022C9 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4575 000022CB 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4576 000022CD 8425[0A6D0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4577 000022D3 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4578                              <1> 
  4579                              <1> TURN_IT_ON:
  4580 000022D5 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4581 000022D7 8A3D[0A6D0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4582 000022DD 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4583 000022E0 8025[0A6D0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4584 000022E7 0825[0A6D0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4585 000022ED A0[0A6D0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4586 000022F2 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4587 000022F4 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4588 000022F7 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4589 000022F8 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4590 000022FA C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4591 000022FD 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4592 000022FF 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4593 00002303 EE                  <1> 	OUT	DX,AL
  4594 00002304 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4595                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4596 00002306 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4597 00002308 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4598 00002309 C3                  <1> 	RETn
  4599                              <1> 
  4600                              <1> NO_MOT_WAIT:
  4601 0000230A FB                  <1> 	sti
  4602                              <1> no_mot_w1: ; 27/02/2015
  4603 0000230B F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4604                              <1> 	;STI				; INTERRUPTS BACK ON
  4605 0000230C C3                  <1> 	RETn
  4606                              <1> 
  4607                              <1> ;-------------------------------------------------------------------------------
  4608                              <1> ; HD_WAIT
  4609                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4610                              <1> ;
  4611                              <1> ; ON ENTRY:	DI = DRIVE #
  4612                              <1> ;
  4613                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4614                              <1> ;-------------------------------------------------------------------------------
  4615                              <1> HD_WAIT:
  4616 0000230D B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4617 0000230F E826FFFFFF          <1> 	CALL	GET_PARM
  4618 00002314 08E4                <1> 	or	ah, ah	; 17/12/2014
  4619 00002316 7519                <1> 	jnz	short DO_WAT
  4620 00002318 F605[0A6D0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4621                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4622                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4623                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4624 0000231F 741E                <1> 	jz	short HW_DONE
  4625 00002321 B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4626 00002323 8A87[196D0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4627 00002329 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4628 0000232B 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4629 0000232D 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4630                              <1> ;GP3:
  4631 0000232F B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4632                              <1> ;	JMP	SHORT DO_WAT
  4633                              <1> 
  4634                              <1> ;ISNT_WRITE:
  4635                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4636                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4637                              <1> 
  4638                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4639                              <1> DO_WAT:
  4640                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4641                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4642                              <1> J29:					; 	1 MILLISECOND LOOP
  4643                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4644 00002331 B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4645 00002336 E87DF1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4646                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4647 0000233B FECC                <1> 	dec	ah
  4648 0000233D 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4649                              <1> HW_DONE:
  4650 0000233F C3                  <1> 	RETn
  4651                              <1> 
  4652                              <1> ;-------------------------------------------------------------------------------
  4653                              <1> ; NEC_OUTPUT
  4654                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4655                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4656                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4657                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4658                              <1> ; 
  4659                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4660                              <1> ;
  4661                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4662                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4663                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4664                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4665                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4666                              <1> ;		AX,CX,DX DESTROYED
  4667                              <1> ;-------------------------------------------------------------------------------
  4668                              <1> 
  4669                              <1> ; 09/12/2014 [Erdogan Tan] 
  4670                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4671                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4672                              <1> ;	This read only register facilitates the transfer of data between
  4673                              <1> ;	the system microprocessor and the controller.
  4674                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4675                              <1> ;	  with the system micrprocessor.
  4676                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4677                              <1> ;	  the transfer is to the controller.
  4678                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4679                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4680                              <1> ; Bit 3 - Reserved.
  4681                              <1> ; Bit 2 - Reserved.
  4682                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4683                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4684                              <1> 
  4685                              <1> ; Data Register (3F5h)
  4686                              <1> ; This read/write register passes data, commands and parameters, and provides
  4687                              <1> ; diskette status information.
  4688                              <1>   		
  4689                              <1> NEC_OUTPUT:
  4690                              <1> 	;PUSH	BX			; SAVE REG.
  4691 00002340 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4692                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4693                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4694                              <1> 	; 16/12/2014
  4695                              <1> 	; waiting for (max.) 0.5 seconds
  4696                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4697                              <1> 	;
  4698                              <1> 	; 17/12/2014
  4699                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4700                              <1> 	;
  4701                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4702                              <1> 	;		go on.
  4703                              <1> 	;INPUT:
  4704                              <1> 	;	AH=Mask for isolation bits.
  4705                              <1> 	;	AL=pattern to look for.
  4706                              <1> 	;	DX=Port to test for
  4707                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4708                              <1> 	;	     (normally 30 microseconds per period.)
  4709                              <1> 	;
  4710                              <1> 	;WFP_SHORT:  
  4711                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4712                              <1> 	;
  4713                              <1> 
  4714                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4715                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4716 00002344 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4717                              <1> ;
  4718                              <1> ;WFPS_OUTER_LP:
  4719                              <1> ;	;
  4720                              <1> ;WFPS_CHECK_PORT:
  4721                              <1> J23:
  4722 00002349 EC                  <1> 	IN	AL,DX			; GET STATUS
  4723 0000234A 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4724 0000234C 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4725 0000234E 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4726                              <1> WFPS_HI:
  4727 00002350 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4728 00002352 A810                <1> 	TEST	AL,010H			; transition on memory
  4729 00002354 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4730                              <1> WFPS_LO:
  4731 00002356 E461                <1> 	IN	AL, PORT_B		; SYS1
  4732 00002358 A810                <1> 	TEST	AL,010H
  4733 0000235A 74FA                <1> 	JZ	SHORT WFPS_LO
  4734                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4735 0000235C E2EB                <1> 	loop	J23	; 27/02/2015
  4736                              <1> ;	;
  4737                              <1> ;	dec	bl
  4738                              <1> ;	jnz	short WFPS_OUTER_LP
  4739                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4740                              <1> ;J23:
  4741                              <1> ;	IN	AL,DX			; GET STATUS
  4742                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4743                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4744                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4745                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4746                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4747                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4748                              <1>    
  4749                              <1> 	;;27/02/2015
  4750                              <1> 	;16/12/2014
  4751                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4752                              <1> 	;;jb	short J23
  4753                              <1> 
  4754                              <1> ;WFPS_TIMEOUT:
  4755                              <1> 
  4756                              <1> ;-----	FALL THRU TO ERROR RETURN
  4757                              <1> 
  4758 0000235E 800D[0C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4759                              <1> 	;POP	BX			; RESTORE REG.
  4760 00002365 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4761 00002366 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4762 00002367 C3                  <1> 	RETn
  4763                              <1> 
  4764                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4765                              <1> 
  4766                              <1> J27:	
  4767 00002368 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4768 0000236A 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4769 0000236C EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4770                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4771                              <1> 	; 27/02/2015
  4772 0000236D 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4773                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4774 0000236E 29C9                <1> 	sub	ecx, ecx
  4775 00002370 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4776 00002372 E841F1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4777 00002377 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4778                              <1> 	;POP	BX			; RESTORE REG
  4779 00002378 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4780                              <1> 
  4781                              <1> ;-------------------------------------------------------------------------------
  4782                              <1> ; SEEK
  4783                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4784                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4785                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4786                              <1> ;
  4787                              <1> ; ON ENTRY:	DI = DRIVE #
  4788                              <1> ;		CH = TRACK #
  4789                              <1> ;
  4790                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4791                              <1> ;		AX,BX,CX DX DESTROYED
  4792                              <1> ;-------------------------------------------------------------------------------
  4793                              <1> SEEK:
  4794 00002379 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4795 0000237B B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4796 0000237D 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4797 0000237F D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4798 00002381 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4799 00002383 8405[096D0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4800 00002389 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4801                              <1> 
  4802 0000238B 0805[096D0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4803 00002391 E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4804 00002396 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4805                              <1> 
  4806                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4807                              <1> 
  4808 00002398 C605[0C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4809 0000239F E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4810 000023A4 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4811                              <1> 
  4812                              <1> AFT_RECAL:
  4813 000023A6 C687[1D6D0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4814 000023AD 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4815 000023AF 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4816                              <1> 
  4817                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4818                              <1> 
  4819 000023B1 F687[196D0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4820 000023B8 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4821 000023BA D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4822                              <1> 
  4823 000023BC 3AAF[1D6D0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4824 000023C2 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4825                              <1> 
  4826 000023C4 BA[F7230000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4827 000023C9 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4828 000023CA 88AF[1D6D0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4829 000023D0 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4830 000023D2 E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4831 000023D7 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4832 000023D9 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4833 000023DB E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4834 000023E0 8AA7[1D6D0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4835 000023E6 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4836 000023EB E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4837                              <1> 
  4838                              <1> ;-----	WAIT FOR HEAD SETTLE
  4839                              <1> 
  4840                              <1> DO_WAIT:
  4841 000023F0 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4842 000023F1 E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4843 000023F6 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4844                              <1> RB:
  4845                              <1> NEC_ERR:
  4846                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4847                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4848 000023F7 C3                  <1> 	RETn				; RETURN TO CALLER
  4849                              <1> 
  4850                              <1> ;-------------------------------------------------------------------------------
  4851                              <1> ; RECAL
  4852                              <1> ;	RECALIBRATE DRIVE
  4853                              <1> ;
  4854                              <1> ; ON ENTRY:	DI = DRIVE #
  4855                              <1> ;
  4856                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4857                              <1> ;-------------------------------------------------------------------------------
  4858                              <1> RECAL:
  4859                              <1> 	;PUSH	CX
  4860                              <1> 	; 24/12/2021
  4861 000023F8 51                  <1> 	push	ecx
  4862 000023F9 B8[15240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4863 000023FE 50                  <1> 	PUSH	eAX
  4864 000023FF B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4865 00002401 E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4866 00002406 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4867 00002408 88DC                <1> 	MOV	AH,BL
  4868 0000240A E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4869 0000240F E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4870 00002414 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4871                              <1> RC_BACK:
  4872                              <1> 	;POP	CX
  4873                              <1> 	; 24/12/2021
  4874 00002415 59                  <1> 	pop	ecx
  4875 00002416 C3                  <1> 	RETn
  4876                              <1> 
  4877                              <1> ;-------------------------------------------------------------------------------
  4878                              <1> ; CHK_STAT_2
  4879                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4880                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4881                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4882                              <1> ;
  4883                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4884                              <1> ;-------------------------------------------------------------------------------
  4885                              <1> CHK_STAT_2:
  4886 00002417 B8[3F240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4887 0000241C 50                  <1> 	PUSH	eAX
  4888 0000241D E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4889 00002422 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4890 00002424 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4891 00002426 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4892 0000242B E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4893 00002430 720C                <1> 	JC	short J34
  4894 00002432 A0[0D6D0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4895 00002437 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4896 00002439 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4897 0000243B 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4898 0000243D F8                  <1> 	CLC				; GOOD RETURN
  4899                              <1> J34:
  4900 0000243E 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4901                              <1> CS_BACK:
  4902 0000243F C3                  <1> 	RETn
  4903                              <1> J35:
  4904 00002440 800D[0C6D0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4905 00002447 F9                  <1> 	STC				; ERROR RETURN CODE
  4906 00002448 EBF4                <1> 	JMP	SHORT J34
  4907                              <1> 
  4908                              <1> ;-------------------------------------------------------------------------------
  4909                              <1> ; WAIT_INT
  4910                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4911                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4912                              <1> ;	IF THE DRIVE IS NOT READY.
  4913                              <1> ;
  4914                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4915                              <1> ;-------------------------------------------------------------------------------
  4916                              <1> 
  4917                              <1> ; 17/12/2014
  4918                              <1> ; 2.5 seconds waiting !
  4919                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4920                              <1> ; amount of time to wait for completion interrupt from NEC.
  4921                              <1> 
  4922                              <1> 
  4923                              <1> WAIT_INT:
  4924 0000244A FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4925 0000244B F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4926                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4927                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4928                              <1> 
  4929                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4930                              <1> 	;
  4931                              <1> 	;WAIT_FOR_MEM:	
  4932                              <1> 	;	Waits for a bit at a specified memory location pointed
  4933                              <1> 	;	to by ES:[DI] to become set.
  4934                              <1> 	;INPUT:
  4935                              <1> 	;	AH=Mask to test with.
  4936                              <1> 	;	ES:[DI] = memory location to watch.
  4937                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4938                              <1> 	;	     (normally 30 microseconds per period.)
  4939                              <1> 
  4940                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4941                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4942                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4943                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4944                              <1> 	; 27/02/2015
  4945 0000244C B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4946                              <1> WFMS_CHECK_MEM:
  4947 00002451 F605[096D0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4948 00002458 7516                <1>         jnz     short J37
  4949                              <1> WFMS_HI:
  4950 0000245A E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4951 0000245C A810                <1> 	TEST	AL,010H			; transition on memory
  4952 0000245E 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4953                              <1> WFMS_LO:
  4954 00002460 E461                <1> 	IN	AL,PORT_B		;SYS1
  4955 00002462 A810                <1> 	TEST	AL,010H
  4956 00002464 74FA                <1> 	JZ	SHORT WFMS_LO
  4957 00002466 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4958                              <1> ;WFMS_OUTER_LP:
  4959                              <1> ;;	or	bl, bl			; check outer counter
  4960                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4961                              <1> ;	dec	bl
  4962                              <1> ;	jz	short J36A	
  4963                              <1> ;	jmp	short WFMS_CHECK_MEM
  4964                              <1> 
  4965                              <1> 	;17/12/2014
  4966                              <1> 	;16/12/2014
  4967                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4968                              <1> ;J36:
  4969                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4970                              <1> ;	JNZ	short J37
  4971                              <1> 	;16/12/2014
  4972                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4973                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4974                              <1> 	;JNZ	short J36
  4975                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4976                              <1> ;	jb	short J36
  4977                              <1> 
  4978                              <1> ;WFMS_TIMEOUT:
  4979                              <1> ;J36A:
  4980 00002468 800D[0C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4981 0000246F F9                  <1> 	STC				; ERROR RETURN
  4982                              <1> J37:
  4983 00002470 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4984 00002471 8025[096D0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4985 00002478 9D                  <1> 	POPF				; RECOVER CARRY
  4986 00002479 C3                  <1> 	RETn				; GOOD RETURN CODE
  4987                              <1> 
  4988                              <1> ;-------------------------------------------------------------------------------
  4989                              <1> ; RESULTS
  4990                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4991                              <1> ;	FOLLOWING AN INTERRUPT.
  4992                              <1> ;
  4993                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4994                              <1> ;		AX,BX,CX,DX DESTROYED
  4995                              <1> ;-------------------------------------------------------------------------------
  4996                              <1> RESULTS:
  4997 0000247A 57                  <1> 	PUSH	eDI
  4998 0000247B BF[0D6D0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4999 00002480 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  5000 00002482 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  5001                              <1> 
  5002                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  5003                              <1> 
  5004                              <1> _R10: 
  5005                              <1> 	; 16/12/2014
  5006                              <1> 	; wait for (max) 0.5 seconds
  5007                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  5008                              <1> 	;XOR	CX,CX			; COUNTER
  5009                              <1> 
  5010                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  5011                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  5012                              <1> 	; 27/02/2015
  5013 00002486 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  5014                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  5015                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  5016                              <1> 
  5017                              <1> WFPSR_OUTER_LP:
  5018                              <1> 	;
  5019                              <1> WFPSR_CHECK_PORT:
  5020                              <1> J39:					; WAIT FOR MASTER
  5021 0000248B EC                  <1> 	IN	AL,DX			; GET STATUS
  5022 0000248C 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5023 0000248E 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5024 00002490 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  5025                              <1> WFPSR_HI:
  5026 00002492 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5027 00002494 A810                <1> 	TEST	AL,010H			; transition on memory
  5028 00002496 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5029                              <1> WFPSR_LO:
  5030 00002498 E461                <1> 	IN	AL, PORT_B		; SYS1
  5031 0000249A A810                <1> 	TEST	AL,010H
  5032 0000249C 74FA                <1> 	JZ	SHORT WFPSR_LO
  5033 0000249E E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5034                              <1> 	;; 27/02/2015
  5035                              <1> 	;;dec	bh
  5036                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5037                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5038                              <1> 
  5039                              <1> 	;;mov	byte [wait_count], 0
  5040                              <1> ;J39:					; WAIT FOR MASTER
  5041                              <1> ;	IN	AL,DX			; GET STATUS
  5042                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5043                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5044                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5045                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5046                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5047                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5048                              <1> 	;
  5049                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5050                              <1> 	;;jb	short J39	
  5051                              <1> 
  5052                              <1> ;WFPSR_TIMEOUT:
  5053 000024A0 800D[0C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5054 000024A7 F9                  <1> 	STC				; SET ERROR RETURN
  5055 000024A8 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5056                              <1> 
  5057                              <1> ;-----	READ IN THE STATUS
  5058                              <1> 
  5059                              <1> J42:
  5060 000024AA EB00                <1> 	JMP	$+2			; I/O DELAY
  5061 000024AC 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5062 000024AE EC                  <1> 	IN	AL,DX			; GET THE DATA
  5063                              <1> 	; 16/12/2014
  5064                              <1> 	NEWIODELAY
  2160 000024AF E6EB                <2>  out 0EBh,al
  5065 000024B1 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5066 000024B3 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5067                              <1> 	; 16/12/2014
  5068                              <1> ;	push	cx
  5069                              <1> ;	mov	cx, 30
  5070                              <1> ;wdw2:
  5071                              <1> ;	NEWIODELAY
  5072                              <1> ;	loop	wdw2
  5073                              <1> ;	pop	cx
  5074                              <1> 
  5075 000024B4 B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5076 000024B9 E8FAEFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5077 000024BE 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5078 000024C0 EC                  <1> 	IN	AL,DX			; GET STATUS
  5079                              <1> 	; 16/12/2014
  5080                              <1> 	NEWIODELAY
  2160 000024C1 E6EB                <2>  out 0EBh,al
  5081                              <1> 	;
  5082 000024C3 A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5083 000024C5 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5084                              <1> 
  5085 000024C7 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5086 000024C9 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5087 000024CB 800D[0C6D0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5088 000024D2 F9                  <1> 	STC				; SET ERROR FLAG
  5089                              <1> 
  5090                              <1> ;-----	RESULT OPERATION IS DONE
  5091                              <1> POPRES:
  5092 000024D3 5F                  <1> 	POP	eDI
  5093 000024D4 C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5094                              <1> 
  5095                              <1> ;-------------------------------------------------------------------------------
  5096                              <1> ; READ_DSKCHNG
  5097                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5098                              <1> ;
  5099                              <1> ; ON ENTRY:	DI = DRIVE #
  5100                              <1> ;
  5101                              <1> ; ON EXIT:	DI = DRIVE #
  5102                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5103                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5104                              <1> ;		AX,CX,DX DESTROYED
  5105                              <1> ;-------------------------------------------------------------------------------
  5106                              <1> READ_DSKCHNG:
  5107 000024D5 E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5108 000024DA 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5109 000024DE EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5110 000024DF A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5111 000024E1 C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5112                              <1> 
  5113                              <1> ;-------------------------------------------------------------------------------
  5114                              <1> ; DRIVE_DET
  5115                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5116                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5117                              <1> ; ON ENTRY:	DI = DRIVE #
  5118                              <1> ;-------------------------------------------------------------------------------
  5119                              <1> DRIVE_DET:
  5120 000024E2 E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5121 000024E7 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5122 000024EC 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5123 000024EE B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5124 000024F0 E884FEFFFF          <1> 	CALL	SEEK
  5125 000024F5 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5126 000024F7 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5127                              <1> SK_GIN:
  5128 000024F9 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5129                              <1> 	;PUSH	CX			; SAVE TRACK
  5130                              <1> 	; 24/12/2021
  5131 000024FB 51                  <1> 	push	ecx
  5132 000024FC E878FEFFFF          <1> 	CALL	SEEK
  5133 00002501 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5134 00002503 B8[3E250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5135 00002508 50                  <1> 	PUSH	eAX
  5136 00002509 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5137 0000250B E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5138 00002510 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5139 00002513 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5140 00002515 E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5141 0000251A E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5142 0000251F 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5143                              <1> 	;POP	CX			; RESTORE TRACK
  5144                              <1> 	; 24/12/2021
  5145 00002520 59                  <1> 	pop	ecx
  5146 00002521 F605[0D6D0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5147 00002528 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5148 0000252A 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5149 0000252C 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5150                              <1> 
  5151                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5152                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5153                              <1> 
  5154 0000252E 808F[196D0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5155 00002535 C3                  <1> 	RETn				; ALL INFORMATION SET
  5156                              <1> IS_80:
  5157 00002536 808F[196D0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5158                              <1> DD_BAC:
  5159 0000253D C3                  <1> 	RETn
  5160                              <1> POP_BAC:
  5161                              <1> 	;POP	CX			; THROW AWAY
  5162                              <1> 	; 24/12/2021
  5163 0000253E 59                  <1> 	pop	ecx
  5164 0000253F C3                  <1> 	RETn
  5165                              <1> 
  5166                              <1> fdc_int:  
  5167                              <1> 	  ; 30/07/2015	
  5168                              <1> 	  ; 16/02/2015
  5169                              <1> ;int_0Eh: ; 11/12/2014
  5170                              <1> 
  5171                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5172                              <1> ; DISK_INT
  5173                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5174                              <1> ;
  5175                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5176                              <1> ;-------------------------------------------------------------------------------
  5177                              <1> DISK_INT_1:
  5178                              <1> 
  5179                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5180                              <1> 	; 24/12/2021
  5181 00002540 50                  <1> 	push	eax
  5182 00002541 1E                  <1> 	push	ds
  5183 00002542 66B81000            <1> 	mov	ax, KDATA
  5184 00002546 8ED8                <1> 	mov 	ds, ax
  5185 00002548 800D[096D0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5186 0000254F B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5187 00002551 E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5188 00002553 1F                  <1> 	pop	ds
  5189                              <1> 	;POP	AX			; RECOVER REGISTER
  5190                              <1> 	; 24/12/2021
  5191 00002554 58                  <1> 	pop	eax
  5192 00002555 CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5193                              <1> 
  5194                              <1> ;-------------------------------------------------------------------------------
  5195                              <1> ; DSKETTE_SETUP
  5196                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5197                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5198                              <1> ;-------------------------------------------------------------------------------
  5199                              <1> DSKETTE_SETUP:
  5200                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5201                              <1> 	;PUSH	BX
  5202                              <1> 	;PUSH	CX
  5203 00002556 52                  <1> 	PUSH	eDX
  5204                              <1> 	;PUSH	DI
  5205                              <1> 	;;PUSH	DS
  5206                              <1> 	; 14/12/2014
  5207                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5208                              <1> 	;mov	[DISK_POINTER+2], cs
  5209                              <1> 	;
  5210                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5211 00002557 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5212 00002559 66C705[196D0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5212 00002561 00                  <1>
  5213 00002562 8025[146D0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5214 00002569 800D[146D0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5215 00002570 C605[096D0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5216 00002577 C605[0B6D0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5217 0000257E C605[0A6D0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5218 00002585 C605[0C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5219                              <1> 	;
  5220                              <1> 	; 28/02/2015
  5221                              <1> 	;mov	word [cfd], 100h 
  5222 0000258C E89DF2FFFF          <1> 	call	DSK_RESET
  5223 00002591 5A                  <1> 	pop	edx
  5224 00002592 C3                  <1> 	retn
  5225                              <1> 
  5226                              <1> ;SUP0:
  5227                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5228                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5229                              <1> ;	; 02/01/2015
  5230                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5231                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5232                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5233                              <1> ;       cmp     byte [fd1_type], 0	
  5234                              <1> ;	jna	short sup1
  5235                              <1> ;	or	di, di
  5236                              <1> ;	jnz	short sup1
  5237                              <1> ;	inc	di
  5238                              <1> ;       jmp     short SUP0
  5239                              <1> ;sup1:
  5240                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5241                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5242                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5243                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5244                              <1> ;	;POP	DI
  5245                              <1> ;	POP	eDX
  5246                              <1> ;	;POP	CX
  5247                              <1> ;	;POP	BX
  5248                              <1> ;	;POP	AX
  5249                              <1> ;	RETn
  5250                              <1> 
  5251                              <1> ;//////////////////////////////////////////////////////
  5252                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5253                              <1> ;
  5254                              <1> 
  5255                              <1> int13h: ; 21/02/2015
  5256 00002593 9C                  <1> 	pushfd
  5257 00002594 0E                  <1> 	push 	cs
  5258 00002595 E859000000          <1> 	call 	DISK_IO
  5259 0000259A C3                  <1> 	retn
  5260                              <1> 
  5261                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5262                              <1> ;/////////////////////////////////////////////////////////////////////
  5263                              <1> 
  5264                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5265                              <1> ; 23/02/2015
  5266                              <1> ; 21/02/2015 (unix386.s)
  5267                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5268                              <1> ;
  5269                              <1> ; Original Source Code:
  5270                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5271                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5272                              <1> ;
  5273                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5274                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5275                              <1> ;
  5276                              <1> 
  5277                              <1> ;The wait for controller to be not busy is 10 seconds.
  5278                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5279                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5280                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5281                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5282                              <1> 
  5283                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5284                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5285                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5286                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5287                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5288                              <1> 
  5289                              <1> ;The wait for Data request on read and write longs is
  5290                              <1> ;2000 us. (?)
  5291                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5292                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5293                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5294                              <1> 
  5295                              <1> ; Port 61h (PORT_B)
  5296                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5297                              <1> 
  5298                              <1> ; 23/12/2014
  5299                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5300                              <1> 
  5301                              <1> ;--- INT 13H -------------------------------------------------------------------
  5302                              <1> ;									       :
  5303                              <1> ; FIXED DISK I/O INTERFACE						       :
  5304                              <1> ;									       :
  5305                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5306                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5307                              <1> ;									       :
  5308                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5309                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5310                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5311                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5312                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5313                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5314                              <1> ;									       :
  5315                              <1> ;------------------------------------------------------------------------------:
  5316                              <1> ;									       :
  5317                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5318                              <1> ;									       :
  5319                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5320                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5321                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5322                              <1> ;			  DL > 80H - DISK				       :
  5323                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5324                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5325                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5326                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5327                              <1> ;	(AH)= 06H  UNUSED						       :
  5328                              <1> ;	(AH)= 07H  UNUSED						       :
  5329                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5330                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5331                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5332                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5333                              <1> ;	(AH)= 0AH  READ LONG						       :
  5334                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5335                              <1> ;	(AH)= 0CH  SEEK 						       :
  5336                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5337                              <1> ;	(AH)= 0EH  UNUSED						       :
  5338                              <1> ;	(AH)= 0FH  UNUSED						       :
  5339                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5340                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5341                              <1> ;	(AH)= 12H  UNUSED						       :
  5342                              <1> ;	(AH)= 13H  UNUSED						       :
  5343                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5344                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5345                              <1> ;									       :
  5346                              <1> ;-------------------------------------------------------------------------------
  5347                              <1> ;									       :
  5348                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5349                              <1> ;									       :
  5350                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5351                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5352                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5353                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5354                              <1> ;									       :
  5355                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5356                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5357                              <1> ;				 (10 BITS TOTAL)			       :
  5358                              <1> ;									       :
  5359                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5360                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5361                              <1> ;									       :
  5362                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5363                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5364                              <1> ;									       :
  5365                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5366                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5367                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5368                              <1> ;			       80H FOR A BAD SECTOR			       :
  5369                              <1> ;			   N = SECTOR NUMBER				       :
  5370                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5371                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5372                              <1> ;									       :
  5373                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5374                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5375                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5376                              <1> ;									       :
  5377                              <1> ;-------------------------------------------------------------------------------
  5378                              <1> 
  5379                              <1> ;-------------------------------------------------------------------------------
  5380                              <1> ; OUTPUT								       :
  5381                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5382                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5383                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5384                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5385                              <1> ;									       :
  5386                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5387                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5388                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5389                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5390                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5391                              <1> ;		REWRITTEN.						       :
  5392                              <1> ;									       :
  5393                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5394                              <1> ;	   INPUT:							       :
  5395                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5396                              <1> ;	   OUTPUT:							       :
  5397                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5398                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5399                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5400                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5401                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5402                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5403                              <1> ;									       :
  5404                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5405                              <1> ;									       :
  5406                              <1> ;	AH = 0 - NOT PRESENT						       :
  5407                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5408                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5409                              <1> ;	     3 - FIXED DISK						       :
  5410                              <1> ;									       :
  5411                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5412                              <1> ;									       :
  5413                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5414                              <1> ;	INFORMATION.							       :
  5415                              <1> ;									       :
  5416                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5417                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5418                              <1> ;									       :
  5419                              <1> ;-------------------------------------------------------------------------------
  5420                              <1> 
  5421                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5422                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5423                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5424                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5425                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5426                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5427                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5428                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5429                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5430                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5431                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5432                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5433                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5434                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5435                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5436                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5437                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5438                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5439                              <1> 
  5440                              <1> ;--------------------------------------------------------
  5441                              <1> ;							:
  5442                              <1> ; FIXED DISK PARAMETER TABLE				:
  5443                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5444                              <1> ;							:
  5445                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5446                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5447                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5448                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5449                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5450                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5451                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5452                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5453                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5454                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5455                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5456                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5457                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5458                              <1> ;							:
  5459                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5460                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5461                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5462                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5463                              <1> ;							:
  5464                              <1> ;--------------------------------------------------------
  5465                              <1> 
  5466                              <1> ;--------------------------------------------------------
  5467                              <1> ;							:
  5468                              <1> ; HARDWARE SPECIFIC VALUES				:
  5469                              <1> ;							:
  5470                              <1> ;  -  CONTROLLER I/O PORT				:
  5471                              <1> ;							:
  5472                              <1> ;     > WHEN READ FROM: 				:
  5473                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5474                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5475                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5476                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5477                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5478                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5479                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5480                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5481                              <1> ;							:
  5482                              <1> ;     > WHEN WRITTEN TO:				:
  5483                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5484                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5485                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5486                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5487                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5488                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5489                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5490                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5491                              <1> ;							:
  5492                              <1> ;--------------------------------------------------------
  5493                              <1> 
  5494                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5495                              <1> ;HF1_PORT	equ	0170h	
  5496                              <1> ;HF_REG_PORT	EQU	03F6H
  5497                              <1> ;HF1_REG_PORT	equ	0376h
  5498                              <1> 
  5499                              <1> HDC1_BASEPORT	equ	1F0h
  5500                              <1> HDC2_BASEPORT	equ	170h		
  5501                              <1> 
  5502 0000259B 90                  <1> align 2
  5503                              <1> 
  5504                              <1> ;-----		STATUS REGISTER
  5505                              <1> 
  5506                              <1> ST_ERROR	EQU	00000001B	;
  5507                              <1> ST_INDEX	EQU	00000010B	;
  5508                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5509                              <1> ST_DRQ		EQU	00001000B	;
  5510                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5511                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5512                              <1> ST_READY	EQU	01000000B	;
  5513                              <1> ST_BUSY 	EQU	10000000B	;
  5514                              <1> 
  5515                              <1> ;-----		ERROR REGISTER
  5516                              <1> 
  5517                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5518                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5519                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5520                              <1> ;		EQU	00001000B	; NOT USED
  5521                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5522                              <1> ;		EQU	00100000B	; NOT USED
  5523                              <1> ERR_DATA_ECC	EQU	01000000B
  5524                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5525                              <1> 
  5526                              <1> 
  5527                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5528                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5529                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5530                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5531                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5532                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5533                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5534                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5535                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5536                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5537                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5538                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5539                              <1> 
  5540                              <1> ;MAX_FILE	EQU	2
  5541                              <1> ;S_MAX_FILE	EQU	2
  5542                              <1> MAX_FILE	equ	4		; 22/12/2014
  5543                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5544                              <1> 
  5545                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5546                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5547                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5548                              <1> 
  5549                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5550                              <1> 
  5551                              <1> ;-----		COMMAND BLOCK REFERENCE
  5552                              <1> 
  5553                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5554                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5555                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5556                              <1> ; 19/12/2014
  5557                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5558                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5559                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5560                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5561                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5562                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5563                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5564                              <1> 
  5565                              <1> align 2
  5566                              <1> 
  5567                              <1> ;----------------------------------------------------------------
  5568                              <1> ; FIXED DISK I/O SETUP						:
  5569                              <1> ;								:
  5570                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5571                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5572                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5573                              <1> ;								:
  5574                              <1> ;----------------------------------------------------------------
  5575                              <1> 
  5576                              <1> DISK_SETUP:
  5577                              <1> 	;CLI
  5578                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5579                              <1> 	;xor	ax,ax
  5580                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5581                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5582                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5583                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5584                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5585                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5586                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5587                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5588                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5589                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5590                              <1> 	;;MOV	[HDISK_INT+2],CS
  5591                              <1> 	;mov	[HDISK_INT1+2],CS
  5592                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5593                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5594                              <1> 	;mov	[HDISK_INT2+2],CS
  5595                              <1> 	;
  5596                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5597                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5598                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5599                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5600                              <1> 	;push	cs
  5601                              <1> 	;pop	ds
  5602                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5603                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5604 0000259C C705[246D0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5604 000025A4 0900                <1>
  5605                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5606                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5607 000025A6 C705[286D0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5607 000025AE 0900                <1>
  5608                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5609                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5610 000025B0 C705[2C6D0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5610 000025B8 0900                <1>
  5611                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5612                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5613 000025BA C705[306D0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5613 000025C2 0900                <1>
  5614                              <1> 	;
  5615                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5616                              <1> 	;;;AND	AL,0BFH
  5617                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5618                              <1> 	;;;JMP	$+2
  5619                              <1> 	;;IODELAY
  5620                              <1> 	;;OUT	INTB01,AL
  5621                              <1> 	;;IODELAY
  5622                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5623                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5624                              <1> 	;;;JMP	$+2
  5625                              <1> 	;;IODELAY
  5626                              <1> 	;;OUT	INTA01,AL
  5627                              <1> 	;
  5628                              <1> 	;STI
  5629                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5630                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5631                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5632                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5633                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5634                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5635                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5636                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5637                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5638                              <1> 	;mov	si, hd0_type
  5639 000025C4 BE[80670000]        <1> 	mov	esi, hd0_type
  5640                              <1> 	;mov	cx, 4
  5641 000025C9 B904000000          <1> 	mov	ecx, 4
  5642                              <1> hde_l:
  5643 000025CE AC                  <1> 	lodsb
  5644 000025CF 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5645 000025D1 7206                <1> 	jb	short _L4
  5646 000025D3 FE05[206D0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5647                              <1> _L4: ; 26/02/2015
  5648 000025D9 E2F3                <1> 	loop	hde_l	
  5649                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5650                              <1> ;L4:
  5651                              <1> 	; 
  5652                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5653                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5654                              <1> 	;;mov 	cl, 3
  5655                              <1> 	;;
  5656                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5657                              <1> ;;hdc_dl:
  5658                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5659                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5660                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5661                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5662                              <1> 	;;jnc	short hdc_reset0
  5663                              <1> 	;;loop	hdc_dl
  5664                              <1> 	;;; 27/12/2014
  5665                              <1> 	;;stc
  5666                              <1> 	;;retn
  5667                              <1> 	;
  5668                              <1> ;;hdc_reset0:
  5669                              <1> 	; 18/01/2015
  5670 000025DB 8A0D[206D0000]      <1> 	mov	cl, [HF_NUM]
  5671 000025E1 20C9                <1> 	and	cl, cl
  5672 000025E3 740D                <1> 	jz	short POD_DONE
  5673                              <1> 	;
  5674 000025E5 B27F                <1> 	mov	dl, 7Fh
  5675                              <1> hdc_reset1:
  5676 000025E7 FEC2                <1> 	inc	dl
  5677                              <1> 	;; 31/12/2015
  5678                              <1> 	;;push	dx
  5679                              <1> 	;;push	cx
  5680                              <1> 	;;push	ds
  5681                              <1> 	;;sub	ax, ax
  5682                              <1> 	;;mov	ds, ax
  5683                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5684                              <1> 	;;pop	ds
  5685                              <1> 	;;MOV	BX,AX
  5686                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5687                              <1> 	;;MOV	CX,AX
  5688                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5689                              <1> 	;;
  5690                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5691                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5692                              <1> 	;;pop	cx
  5693                              <1> 	;;pop	dx
  5694                              <1> 	;;
  5695                              <1> 	; 18/01/2015
  5696 000025E9 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5697                              <1> 	;int	13h
  5698 000025EB E8A3FFFFFF          <1> 	call	int13h
  5699 000025F0 E2F5                <1> 	loop	hdc_reset1
  5700                              <1> POD_DONE:
  5701 000025F2 C3                  <1> 	RETn
  5702                              <1> 
  5703                              <1> ;;-----	POD_ERROR
  5704                              <1> 
  5705                              <1> ;;CTL_ERRX:
  5706                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5707                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5708                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5709                              <1> ;	;JMP	short POD_DONE
  5710                              <1> 
  5711                              <1> ;;HD_RESET_1:
  5712                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5713                              <1> ;;	;PUSH	CX
  5714                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5715                              <1> ;;	INT	13H
  5716                              <1> ;;	JC	short RES_2
  5717                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5718                              <1> ;;	INT	13H
  5719                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5720                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5721                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5722                              <1> ;;					; (30 seconds)		
  5723                              <1> ;;	;cmc
  5724                              <1> ;;	;JNC	short RES_1
  5725                              <1> ;;	jb	short RES_1
  5726                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5727                              <1> ;;	;TEST	DL,1
  5728                              <1> ;;	;JNZ	RES_E1
  5729                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5730                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5731                              <1> ;;	;JMP	SHORT RES_E1
  5732                              <1> ;;RES_ER: ; 22/12/2014
  5733                              <1> ;;RES_OK:
  5734                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5735                              <1> ;;	;POP	BX
  5736                              <1> ;;	RETn
  5737                              <1> ;;
  5738                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5739                              <1> ;;	INT	13H
  5740                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5741                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5742                              <1> ;;	INT	13H
  5743                              <1> ;;	JC	short RES_ER
  5744                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5745                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5746                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5747                              <1> ;;	INT	13H
  5748                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5749                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5750                              <1> ;;	JE	short RES_OK
  5751                              <1> ;;	CMP	AH,DATA_CORRECTED
  5752                              <1> ;;	JE	short RES_OK
  5753                              <1> ;;	CMP	AH,BAD_ECC
  5754                              <1> ;;	JE	short RES_OK
  5755                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5756                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5757                              <1> ;;					; (60 seconds)		
  5758                              <1> ;;	cmc
  5759                              <1> ;;	JC	short RES_ER		; FAILED
  5760                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5761                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5762                              <1> ;;	AND	AL,3FH
  5763                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5764                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5765                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5766                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5767                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5768                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5769                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5770                              <1> ;;	;TEST	DL,1
  5771                              <1> ;;	;JNZ	short RES_E1
  5772                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5773                              <1> ;;;RES_E1:
  5774                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5775                              <1> ;;;RES_OK:
  5776                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5777                              <1> ;;	;POP	BX
  5778                              <1> ;;	;RETn
  5779                              <1> ;
  5780                              <1> ;;SET_FAIL:
  5781                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5782                              <1> ;	;CALL	CMOS_READ
  5783                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5784                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5785                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5786                              <1> ;	;RETn
  5787                              <1> ;
  5788                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5789                              <1> ;	;POP	AX			; SAVE RETURN
  5790                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5791                              <1> ;	;POP	BX
  5792                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5793                              <1> ;	;PUSH	CX
  5794                              <1> ;	;PUSH	AX
  5795                              <1> ;	;push	ds
  5796                              <1> ;	;xor	ax, ax
  5797                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5798                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5799                              <1> ;	;				; BX = START TIME
  5800                              <1> ;	;				; CX = END TIME
  5801                              <1> ;	;pop	ds
  5802                              <1> ;	;CMP	BX,CX
  5803                              <1> ;	;JB	short TCHK1		; START < END
  5804                              <1> ;	;CMP	BX,AX
  5805                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5806                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5807                              <1> ;;TCHK1: CMP	AX,BX
  5808                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5809                              <1> ;;TCHK2: CMP	AX,CX
  5810                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5811                              <1> ;;					; OR CURRENT < END < START
  5812                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5813                              <1> ;;	RETn
  5814                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5815                              <1> ;;	RETn
  5816                              <1> ;;
  5817                              <1> ;;int_13h:
  5818                              <1> 
  5819                              <1> ;----------------------------------------
  5820                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5821                              <1> ;----------------------------------------
  5822                              <1> 
  5823                              <1> DISK_IO:
  5824 000025F3 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5825                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5826                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5827                              <1> 	;;call	int40h
  5828                              <1> 	;jb	DISKETTE_IO_1
  5829                              <1> 	; 24/12/2021
  5830 000025F6 7305                <1> 	jnb	short A1
  5831 000025F8 E95FF1FFFF          <1> 	jmp	DISKETTE_IO_1
  5832                              <1> ;RET_2:
  5833                              <1> 	;RETf	2			; BACK TO CALLER
  5834                              <1> ;	retf	4
  5835                              <1> A1:
  5836 000025FD FB                  <1> 	STI				; ENABLE INTERRUPTS
  5837                              <1> 	;; 04/01/2015
  5838                              <1> 	;;OR	AH,AH
  5839                              <1> 	;;JNZ	short A2
  5840                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5841                              <1> 	;;SUB	AH,AH
  5842 000025FE 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5843 00002601 772E                <1> 	JA	short RET_2
  5844                              <1> 	; 18/01/2015
  5845 00002603 08E4                <1> 	or	ah,ah
  5846 00002605 742D                <1> 	jz	short A4
  5847 00002607 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5848 0000260A 7504                <1> 	jne	short A2
  5849 0000260C 28E4                <1> 	sub	ah,ah	; Reset
  5850 0000260E EB24                <1> 	jmp	short A4
  5851                              <1> A2:
  5852 00002610 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5853                              <1> 	;JNZ	short A3
  5854                              <1>         ;JMP    GET_PARM_N
  5855                              <1> 	;je	GET_PARM_N
  5856                              <1> 	; 24/12/2021
  5857 00002613 7505                <1> 	jne	short A3
  5858 00002615 E90D030000          <1> 	jmp	GET_PARM_N
  5859                              <1> A3:	
  5860 0000261A 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5861                              <1> 	;JNZ	short A4
  5862                              <1>         ;JMP    READ_DASD_TYPE
  5863                              <1> 	;je	READ_DASD_TYPE
  5864                              <1> 	; 24/12/2021
  5865 0000261D 7505                <1> 	jne	short A3_A4
  5866 0000261F E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5867                              <1> A3_A4:
  5868                              <1> 	; 02/02/2015
  5869 00002624 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5870                              <1> 	; 12/01/2015
  5871 00002627 F5                  <1> 	cmc
  5872 00002628 730A                <1> 	jnc	short A4
  5873                              <1> 	; 30/01/2015
  5874                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5875 0000262A C605[1F6D0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5876                              <1> 	;jmp	short RET_2
  5877                              <1> RET_2:
  5878 00002631 CA0400              <1> 	retf	4
  5879                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5880 00002634 C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5881 00002638 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5882 00002639 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5883 0000263A 52                  <1> 	PUSH	eDX
  5884 0000263B 1E                  <1> 	PUSH	DS
  5885 0000263C 06                  <1> 	PUSH	ES
  5886 0000263D 56                  <1> 	PUSH	eSI
  5887 0000263E 57                  <1> 	PUSH	eDI
  5888                              <1> 	;;04/01/2015
  5889                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5890                              <1> 	;;JNZ	short A5
  5891                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5892                              <1> ;;A5:	
  5893                              <1> 	;push	cs
  5894                              <1> 	;pop	ds
  5895                              <1> 	; 21/02/2015
  5896                              <1> 	;push	ax
  5897                              <1> 	; 24/12/2021
  5898 0000263F 50                  <1> 	push	eax
  5899 00002640 66B81000            <1> 	mov	ax, KDATA
  5900 00002644 8ED8                <1> 	mov	ds, ax
  5901 00002646 8EC0                <1> 	mov	es, ax	
  5902                              <1> 	;pop	ax
  5903                              <1> 	; 24/12/2021
  5904 00002648 58                  <1> 	pop	eax
  5905 00002649 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5906                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5907 0000264E 8A25[1F6D0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5908 00002654 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5909 00002657 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5910 00002658 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5911 00002659 5E                  <1> 	POP	eSI
  5912 0000265A 07                  <1>         POP     ES
  5913 0000265B 1F                  <1>         POP     DS
  5914 0000265C 5A                  <1> 	POP	eDX
  5915 0000265D 59                  <1> 	POP	eCX
  5916 0000265E 5B                  <1> 	POP	eBX
  5917 0000265F C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5918                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5919 00002660 CA0400              <1> 	retf	4
  5920                              <1> ; 21/02/2015
  5921                              <1> ;       dw --> dd
  5922                              <1> M1:					; FUNCTION TRANSFER TABLE
  5923 00002663 [1C280000]          <1> 	dd	DISK_RESET		; 000H
  5924 00002667 [91280000]          <1> 	dd	RETURN_STATUS		; 001H
  5925 0000266B [9E280000]          <1> 	dd	DISK_READ		; 002H
  5926 0000266F [A7280000]          <1> 	dd	DISK_WRITE		; 003H
  5927 00002673 [B0280000]          <1> 	dd	DISK_VERF		; 004H
  5928 00002677 [C8280000]          <1> 	dd	FMT_TRK 		; 005H
  5929 0000267B [12280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5930 0000267F [12280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5931 00002683 [12280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5932 00002687 [89290000]          <1> 	dd	INIT_DRV		; 009H
  5933 0000268B [E8290000]          <1> 	dd	RD_LONG 		; 00AH
  5934 0000268F [F1290000]          <1> 	dd	WR_LONG 		; 00BH
  5935 00002693 [FA290000]          <1> 	dd	DISK_SEEK		; 00CH
  5936 00002697 [1C280000]          <1> 	dd	DISK_RESET		; 00DH
  5937 0000269B [12280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5938 0000269F [12280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5939 000026A3 [222A0000]          <1> 	dd	TST_RDY 		; 010H
  5940 000026A7 [462A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5941 000026AB [12280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5942 000026AF [12280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5943 000026B3 [7C2A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5944                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5945 000026B7 [12280000]          <1> 	dd	BAD_COMMAND		; 015h
  5946 000026BB [12280000]          <1> 	dd	BAD_COMMAND		; 016h
  5947 000026BF [12280000]          <1> 	dd	BAD_COMMAND		; 017h
  5948 000026C3 [12280000]          <1> 	dd	BAD_COMMAND		; 018h
  5949 000026C7 [12280000]          <1> 	dd	BAD_COMMAND		; 019h
  5950 000026CB [12280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5951 000026CF [9E280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5952 000026D3 [A7280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5953                              <1> M1L     EQU    $-M1
  5954                              <1> 
  5955                              <1> DISK_IO_CONT:
  5956                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5957 000026D7 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5958                              <1> 	;;JNZ	short SU0
  5959                              <1>         ;;JMP	RETURN_STATUS
  5960                              <1> 	;je	RETURN_STATUS
  5961                              <1> 	; 24/12/2021
  5962 000026DA 7505                <1> 	jne	short SU0
  5963 000026DC E9B0010000          <1> 	jmp	RETURN_STATUS
  5964                              <1> SU0:
  5965 000026E1 C605[1F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5966                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5967                              <1> 	;mov	si, bx ;; 14/02/2015
  5968 000026E8 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5969 000026EA 8A1D[206D0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5970                              <1> 	;; 04/01/2015
  5971                              <1> 	;;PUSH	AX
  5972 000026F0 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5973                              <1> 					; (get drive number as 0 to 3)
  5974 000026F3 38D3                <1> 	CMP	BL,DL
  5975                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5976                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5977                              <1> 	; 24/12/2021
  5978 000026F5 7705                <1> 	ja	short su0_su1
  5979 000026F7 E916010000          <1> 	jmp	BAD_COMMAND
  5980                              <1> su0_su1:
  5981                              <1>         ;;03/01/2015
  5982 000026FC 29DB                <1> 	sub	ebx, ebx
  5983 000026FE 88D3                <1> 	mov	bl, dl
  5984                              <1> 	;sub	bh, bh
  5985 00002700 883D[346D0000]      <1> 	mov	[LBAMode], bh 	; 0
  5986                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5987                              <1> 	;test	byte [ebx+hd0_type], 1
  5988                              <1> 	;jz	short su1		; no
  5989                              <1> 	;inc	byte [LBAMode]
  5990                              <1> ;su1:
  5991                              <1> 	; 21/02/2015 (32 bit modification)
  5992                              <1> 	; 04/01/2015
  5993                              <1> 	;push	ax ; ***
  5994                              <1> 	; 24/12/2021
  5995 00002706 50                  <1> 	push	eax ; ***
  5996                              <1> 	;PUSH	ES ; **
  5997                              <1> 	;PUSH	DX ; *
  5998                              <1> 	; 24/12/2021
  5999 00002707 52                  <1> 	push	edx ; *
  6000                              <1> 	;push	ax
  6001 00002708 50                  <1> 	push	eax
  6002 00002709 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  6003                              <1> 	; 02/02/2015
  6004                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  6005 0000270E 668B4310            <1> 	mov	ax, [ebx+16]
  6006 00002712 66A3[74670000]      <1> 	mov	[HF_PORT], ax
  6007                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  6008 00002718 668B5312            <1> 	mov	dx, [ebx+18]
  6009 0000271C 668915[76670000]    <1> 	mov	[HF_REG_PORT], dx
  6010                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  6011 00002723 8A4314              <1> 	mov	al, [ebx+20]
  6012                              <1> 	; 23/02/2015
  6013 00002726 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  6014 00002728 7406                <1> 	jz 	short su1
  6015 0000272A FE05[346D0000]      <1> 	inc	byte [LBAMode] ; 1 
  6016                              <1> su1: 	 
  6017 00002730 C0E804              <1> 	shr 	al, 4
  6018 00002733 2401                <1> 	and	al, 1			
  6019 00002735 A2[78670000]        <1> 	mov	[hf_m_s], al 
  6020                              <1> 	;
  6021                              <1> 	; 03/01/2015
  6022                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  6023 0000273A 8A4308              <1> 	mov	al, [ebx+8]
  6024                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  6025 0000273D EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6026                              <1> 					; Control Byte:  (= 08h, here)
  6027                              <1> 					; bit 0 - 0
  6028                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6029                              <1> 					; bit 2 - SRST (software RESET)
  6030                              <1> 					; bit 3 - use extra heads (8 to 15)
  6031                              <1> 					;         -always set to 1-	
  6032                              <1> 					; (bits 3 to 7 are reserved
  6033                              <1> 					;          for ATA devices)
  6034 0000273E 8A25[216D0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6035 00002744 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6036 00002747 08C4                <1> 	OR	AH,AL
  6037 00002749 8825[216D0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6038                              <1> 	; 04/01/2015
  6039                              <1> 	;pop	ax
  6040                              <1> 	; 24/12/2021
  6041 0000274F 58                  <1> 	pop	eax
  6042                              <1> 	;pop	dx ; * ;; 14/02/2015
  6043                              <1> 	; 24/12/2021
  6044 00002750 5A                  <1> 	pop	edx ; *
  6045 00002751 20E4                <1> 	and	ah, ah	; Reset function ?
  6046 00002753 7506                <1> 	jnz	short su2
  6047                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6048                              <1> 	;pop	es ; **
  6049                              <1> 	;pop	ax ; ***
  6050                              <1> 	; 24/12/2021
  6051 00002755 58                  <1> 	pop	eax ; ***	
  6052                              <1> 	;;pop	bx
  6053 00002756 E9C1000000          <1>         jmp     DISK_RESET
  6054                              <1> su2:
  6055 0000275B 803D[346D0000]00    <1> 	cmp	byte [LBAMode], 0
  6056 00002762 765E                <1> 	jna	short su3
  6057                              <1> 	;
  6058                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6059 00002764 80FC1B              <1> 	cmp	ah, 1Bh
  6060 00002767 720B                <1> 	jb	short lbarw1
  6061 00002769 80FC1C              <1> 	cmp	ah, 1Ch
  6062 0000276C 7759                <1> 	ja 	short invldfnc
  6063                              <1> 	;;pop	dx ; * ; 14/02/2015
  6064                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6065 0000276E 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6066                              <1> 	;; 14/02/2015
  6067 00002770 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6068                              <1> 	;;mov	dx, bx
  6069                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6070                              <1> 	;;mov	bx, di
  6071                              <1> 	;mov	si, di ; Buffer offset
  6072 00002772 EB2E                <1> 	jmp	short lbarw2
  6073                              <1> lbarw1:
  6074                              <1> 	; convert CHS to LBA
  6075                              <1> 	;
  6076                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6077                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6078                              <1> 	;	+ Sector - 1
  6079                              <1> 	;push	dx ; * ;; 14/02/2015
  6080                              <1> 	; 24/12/2021
  6081 00002774 52                  <1> 	push	edx ; *
  6082                              <1> 	;xor	dh, dh
  6083 00002775 31D2                <1> 	xor	edx, edx
  6084                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6085 00002777 8A530E              <1> 	mov	dl, [ebx+14]
  6086                              <1> 	;xor	ah, ah
  6087 0000277A 31C0                <1> 	xor	eax, eax
  6088                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6089 0000277C 8A4302              <1> 	mov	al, [ebx+2]
  6090 0000277F FEC8                <1> 	dec	al
  6091                              <1> 	;inc	ax		; 0 =  256
  6092 00002781 40                  <1> 	inc	eax ; 24/12/2021
  6093 00002782 66F7E2              <1> 	mul 	dx
  6094                              <1> 		; AX = # of Heads" * Sectors/Track
  6095 00002785 6689CA              <1> 	mov	dx, cx
  6096                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6097 00002788 83E13F              <1> 	and	ecx, 3fh
  6098 0000278B 86D6                <1> 	xchg	dl, dh
  6099 0000278D C0EE06              <1> 	shr	dh, 6
  6100                              <1> 		; DX = cylinder (0 to 1023)
  6101                              <1> 	;mul 	dx
  6102                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6103 00002790 F7E2                <1> 	mul	edx
  6104 00002792 FEC9                <1> 	dec	cl  ; sector - 1
  6105                              <1> 	;add	ax, cx
  6106                              <1> 	;adc	dx, 0
  6107                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6108 00002794 01C8                <1> 	add	eax, ecx
  6109                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6110                              <1> 	; 24/12/2021
  6111 00002796 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6112                              <1> 	;push	dx
  6113                              <1> 	;push	ax
  6114 00002797 50                  <1> 	push	eax
  6115                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6116 00002798 8A430E              <1> 	mov	al, [ebx+14]
  6117 0000279B F6E5                <1> 	mul	ch
  6118                              <1> 		; AX = Head * Sectors/Track
  6119 0000279D 6699                <1>         cwd
  6120                              <1> 	;pop	dx
  6121 0000279F 5A                  <1> 	pop	edx
  6122                              <1> 	;add	ax, dx
  6123                              <1> 	;pop	dx
  6124                              <1> 	;adc	dx, 0 ; add carry bit
  6125 000027A0 01D0                <1> 	add	eax, edx
  6126                              <1> lbarw2:
  6127 000027A2 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6128 000027A4 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6129 000027A6 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6130                              <1> 				; NOTE: Features register (1F1h, 171h)
  6131                              <1> 				; is not used for ATA device R/W functions. 
  6132                              <1> 				; It is old/obsolete 'write precompensation'
  6133                              <1> 				; register and error register
  6134                              <1> 				; for old ATA/IDE devices.
  6135                              <1> 	; 18/01/2014
  6136                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6137 000027AA 8A0D[78670000]      <1> 	mov	cl, [hf_m_s]
  6138                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6139                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6140                              <1> 				; bit 6 = 1 = LBA mode
  6141                              <1> 				; bit 7 = 1
  6142 000027B0 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6143                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6144 000027B3 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6145 000027B8 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6146                              <1> 	;or	dh, ch
  6147 000027BB 09C8                <1> 	or	eax, ecx	
  6148                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6149                              <1> 				  ; (Sector Number Register)
  6150                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6151                              <1> 				  ; (Cylinder Low Register)
  6152                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6153                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6154                              <1> 				  ; (Cylinder High Register)
  6155                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6156                              <1> 				  ; (Drive/Head Register)
  6157                              <1> 	
  6158                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6159 000027BD 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6160                              <1> 	;14/02/2015
  6161                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6162 000027C0 EB37                <1> 	jmp	short su4
  6163                              <1> su3:
  6164                              <1> 	; 02/02/2015 
  6165                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6166 000027C2 80FC14              <1> 	cmp 	ah, 14h
  6167 000027C5 7603                <1> 	jna 	short chsfnc
  6168                              <1> invldfnc:
  6169                              <1>         ; 14/02/2015  
  6170                              <1> 	;pop	es ; **
  6171                              <1>         ;pop	ax ; ***
  6172                              <1>         ; 24/12/2021
  6173 000027C7 58                  <1> 	pop	eax ; ***
  6174                              <1> 	;jmp	short BAD_COMMAND_POP
  6175 000027C8 EB48                <1>         jmp     short BAD_COMMAND
  6176                              <1> chsfnc:	
  6177                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6178 000027CA 668B4305            <1> 	mov	ax, [ebx+5]
  6179 000027CE 66C1E802            <1> 	SHR	AX,2
  6180 000027D2 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6181                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6182                              <1> 	;;PUSH	DX
  6183                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6184                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6185                              <1> 	;;POP	DX ; * 
  6186                              <1> 	;;POP	ES ; **
  6187                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6188                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6189                              <1> 	;;OR	AH,AL
  6190                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6191                              <1> 	;
  6192 000027D5 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6193 000027D7 243F                <1> 	AND	AL,3FH
  6194 000027D9 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6195 000027DC 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6196 000027DF 88C8                <1> 	MOV	AL,CL
  6197 000027E1 C0E806              <1> 	SHR	AL,6
  6198 000027E4 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6199                              <1> 	;;05/01/2015
  6200                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6201 000027E7 A0[78670000]        <1> 	mov	al, [hf_m_s]
  6202 000027EC C0E004              <1> 	SHL	AL,4
  6203 000027EF 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6204 000027F2 08F0                <1> 	OR	AL,DH
  6205                              <1> 	;OR	AL,80H or 20H
  6206 000027F4 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6207 000027F6 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6208                              <1> su4:
  6209                              <1> 	;POP	ES ; **
  6210                              <1>         ;; 14/02/2015
  6211                              <1>         ;;POP   AX
  6212                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6213                              <1>         ;;PUSH  AX
  6214                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6215                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6216                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6217                              <1> 	;pop     ax ; ***
  6218                              <1> 	; 24/12/2021
  6219 000027F9 58                  <1> 	pop	eax ; ***
  6220 000027FA 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6221 000027FD 29DB                <1>         sub	ebx, ebx
  6222 000027FF 88E3                <1> 	mov     bl, ah
  6223                              <1>         ;xor	bh, bh
  6224                              <1>         ;sal	bx, 1
  6225 00002801 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6226                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6227                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6228                              <1>         ;;JNB   short BAD_COMMAND_POP
  6229                              <1>         ;cmp	bx, M1L
  6230 00002805 83FB74              <1> 	cmp	ebx, M1L
  6231 00002808 7308                <1> 	jnb	short BAD_COMMAND
  6232                              <1>         ;xchg	bx, si
  6233 0000280A 87DE                <1>         xchg	ebx, esi
  6234                              <1> 	;;;POP	AX			; RESTORE AX
  6235                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6236                              <1> 	
  6237                              <1> 	;;PUSH	CX
  6238                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6239                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6240                              <1> 	;SHR	CX,4
  6241                              <1> 	;MOV	AX,ES
  6242                              <1> 	;ADD	AX,CX
  6243                              <1> 	;MOV	ES,AX
  6244                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6245                              <1> 	;;POP	AX
  6246                              <1> 	;;POP	CX
  6247                              <1> 	;;JMP	word [CS:SI+M1]
  6248                              <1> 	;jmp	word [SI+M1]
  6249 0000280C FFA6[63260000]      <1> 	jmp	dword [esi+M1]
  6250                              <1> ;;BAD_COMMAND_POP:
  6251                              <1> ;;	POP	AX
  6252                              <1> ;;	POP	BX
  6253                              <1> BAD_COMMAND:
  6254 00002812 C605[1F6D0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6255 00002819 B000                <1> 	MOV	AL,0
  6256 0000281B C3                  <1> 	RETn
  6257                              <1> 
  6258                              <1> ;----------------------------------------
  6259                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6260                              <1> ;----------------------------------------
  6261                              <1> 
  6262                              <1> ; 18-1-2015 : one controller reset (not other one)
  6263                              <1> 
  6264                              <1> DISK_RESET:
  6265 0000281C FA                  <1> 	CLI
  6266 0000281D E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6267                              <1> 	;JMP	$+2
  6268                              <1> 	IODELAY
  2155 0000281F EB00                <2>  jmp short $+2
  2156 00002821 EB00                <2>  jmp short $+2
  6269                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6270 00002823 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6271 00002825 E6A1                <1> 	OUT	INTB01,AL
  6272 00002827 FB                  <1> 	STI				; START INTERRUPTS
  6273                              <1> 	; 14/02/2015
  6274                              <1> 	;mov	di, dx
  6275                              <1> 	; 24/12/2021
  6276 00002828 89D7                <1> 	mov	edi, edx	
  6277                              <1> 	; 04/01/2015
  6278                              <1> 	;xor	di,di
  6279                              <1> drst0:
  6280 0000282A B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6281                              <1> 	;MOV	DX,HF_REG_PORT
  6282 0000282C 668B15[76670000]    <1> 	MOV	DX,[HF_REG_PORT]
  6283 00002833 EE                  <1> 	OUT	DX,AL			; RESET
  6284                              <1> ;	MOV	CX,10			; DELAY COUNT
  6285                              <1> ;DRD:	DEC	CX
  6286                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6287                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6288 00002834 B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6289 00002839 E87AECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6290                              <1>                                         ; 40 micro seconds)
  6291 0000283E A0[216D0000]        <1> 	mov	al,[CONTROL_BYTE]
  6292 00002843 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6293 00002845 EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6294 00002846 E807040000          <1> 	CALL	NOT_BUSY
  6295 0000284B 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6296 0000284D 668B15[74670000]    <1> 	MOV	DX,[HF_PORT]
  6297 00002854 FEC2                <1> 	inc	dl  ; HF_PORT+1
  6298                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6299                              <1>         ;mov	cl, 10
  6300 00002856 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6301                              <1> drst1:
  6302 0000285B EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6303 0000285C 3C01                <1> 	CMP	AL,1
  6304                              <1> 	; 04/01/2015
  6305 0000285E 740A                <1> 	jz	short drst2
  6306                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6307                              <1>         	; Drive/Head Register - bit 4
  6308 00002860 E2F9                <1> 	loop	drst1
  6309                              <1> DRERR:	
  6310 00002862 C605[1F6D0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6311 00002869 C3                  <1> 	RETn
  6312                              <1> drst2:
  6313                              <1> 	; 14/02/2015
  6314                              <1> 	;mov	dx, di
  6315                              <1> 	; 24/12/2021
  6316 0000286A 89FA                <1> 	mov	edx, edi
  6317                              <1> ;drst3:
  6318                              <1> ;	; 05/01/2015
  6319                              <1> ;	shl 	di,1
  6320                              <1> ;	; 04/01/2015
  6321                              <1> ;	mov	ax,[di+hd_cports]
  6322                              <1> ;	cmp	ax,[HF_REG_PORT]
  6323                              <1> ;	je	short drst4
  6324                              <1> ;	mov	[HF_REG_PORT], ax
  6325                              <1> ;	; 03/01/2015
  6326                              <1> ;	mov	ax,[di+hd_ports]
  6327                              <1> ;       mov     [HF_PORT], ax
  6328                              <1> ;	; 05/01/2014
  6329                              <1> ;	shr	di,1
  6330                              <1> ;	; 04/01/2015
  6331                              <1> ;	jmp	short drst0	; reset other controller
  6332                              <1> ;drst4:
  6333                              <1> ;	; 05/01/2015
  6334                              <1> ;	shr	di,1
  6335                              <1> ;	mov	al,[di+hd_dregs]
  6336                              <1> ;	and	al,10h ; bit 4 only
  6337                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6338                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6339                              <1> 	;
  6340 0000286C A0[78670000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6341 00002871 A801                <1> 	test	al,1
  6342                              <1> ;	jnz	short drst6
  6343 00002873 7516                <1>         jnz     short drst4
  6344 00002875 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6345                              <1> ;drst5:
  6346                              <1> drst3:
  6347 00002879 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6348                              <1> 	;mov	dx,di
  6349 0000287E E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6350                              <1> 	; 04/01/2014
  6351                              <1> ;	inc	di
  6352                              <1> ;	mov	dx,di
  6353                              <1> ;	cmp	dl,[HF_NUM]
  6354                              <1> ;	jb	short drst3
  6355                              <1> ;DRE:
  6356 00002883 C605[1F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6357 0000288A C3                  <1> 	RETn
  6358                              <1> ;drst6:
  6359                              <1> drst4:		; Drive/Head Register - bit 4
  6360 0000288B 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6361                              <1>         ;jmp    short drst5
  6362 0000288F EBE8                <1>         jmp     short drst3
  6363                              <1> 
  6364                              <1> ;----------------------------------------
  6365                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6366                              <1> ;----------------------------------------
  6367                              <1> 
  6368                              <1> RETURN_STATUS:
  6369 00002891 A0[1F6D0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6370 00002896 C605[1F6D0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6371 0000289D C3                  <1> 	RETn
  6372                              <1> 
  6373                              <1> ;----------------------------------------
  6374                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6375                              <1> ;----------------------------------------
  6376                              <1> 
  6377                              <1> DISK_READ:
  6378 0000289E C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6379 000028A2 E92A020000          <1>         JMP     COMMANDI
  6380                              <1> 
  6381                              <1> ;----------------------------------------
  6382                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6383                              <1> ;----------------------------------------
  6384                              <1> 
  6385                              <1> DISK_WRITE:
  6386 000028A7 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6387 000028AB E976020000          <1>         JMP     COMMANDO
  6388                              <1> 
  6389                              <1> ;----------------------------------------
  6390                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6391                              <1> ;----------------------------------------
  6392                              <1> 
  6393                              <1> DISK_VERF:
  6394 000028B0 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6395 000028B4 E8E4020000          <1> 	CALL	COMMAND
  6396 000028B9 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6397 000028BB E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6398 000028C0 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6399 000028C2 E8E3030000          <1> 	CALL	CHECK_STATUS
  6400                              <1> VERF_EXIT:
  6401 000028C7 C3                  <1> 	RETn
  6402                              <1> 
  6403                              <1> ;----------------------------------------
  6404                              <1> ;	FORMATTING	     (AH = 05H) :
  6405                              <1> ;----------------------------------------
  6406                              <1> 
  6407                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6408 000028C8 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6409                              <1> 	;PUSH	ES
  6410                              <1> 	;PUSH	BX
  6411 000028CC 53                  <1> 	push	ebx
  6412 000028CD E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6413                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6414 000028D2 8A430E              <1> 	mov	al, [ebx+14]
  6415 000028D5 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6416 000028D8 5B                  <1> 	pop	ebx
  6417                              <1> 	;POP	BX
  6418                              <1> 	;POP	ES
  6419 000028D9 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6420                              <1> 
  6421                              <1> ;----------------------------------------
  6422                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6423                              <1> ;----------------------------------------
  6424                              <1> 
  6425                              <1> READ_DASD_TYPE:
  6426                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6427 000028DE 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6428                              <1> 	;PUSH	ES
  6429 000028DF 53                  <1> 	PUSH	eBX
  6430                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6431                              <1> 	;push	cs
  6432                              <1> 	;pop	ds
  6433 000028E0 66BB1000            <1>         mov	bx, KDATA
  6434 000028E4 8EDB                <1> 	mov	ds, bx
  6435                              <1> 	;mov	es, bx
  6436 000028E6 C605[1F6D0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6437 000028ED 8A1D[206D0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6438 000028F3 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6439 000028F6 38D3                <1> 	CMP	BL,DL
  6440 000028F8 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6441 000028FA E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6442                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6443 000028FF 8A4302              <1> 	mov	al, [ebx+2]
  6444                              <1> 	;MOV	CL,[ES:BX+14]
  6445 00002902 8A4B0E              <1> 	mov	cl, [ebx+14]
  6446 00002905 F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6447                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6448 00002907 668B0B              <1> 	mov	cx, [ebx]
  6449                              <1> 	;
  6450                              <1> 	; 02/01/2015 
  6451                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6452                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6453 0000290A 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6454                              <1> 	;
  6455 0000290C 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6456 0000290F 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6457 00002912 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6458                              <1> 	;SUB	AX,AX
  6459 00002915 28C0                <1> 	sub	al, al
  6460 00002917 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6461 00002919 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6462                              <1> 	;POP	ES
  6463 0000291A 1F                  <1> 	POP	DS
  6464 0000291B F8                  <1> 	CLC				; CLEAR CARRY
  6465                              <1> 	;RETf	2
  6466 0000291C CA0400              <1> 	retf	4
  6467                              <1> RDT_NOT_PRESENT:
  6468                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6469                              <1> 	; 24/12/2021
  6470 0000291F 29C0                <1> 	sub	eax, eax
  6471                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6472                              <1> 	;MOV	DX,AX
  6473 00002921 89C1                <1> 	mov	ecx, eax
  6474 00002923 89C2                <1> 	mov	edx, eax
  6475 00002925 EBF2                <1> 	JMP	short RDT2
  6476                              <1> 
  6477                              <1> ;----------------------------------------
  6478                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6479                              <1> ;----------------------------------------
  6480                              <1> 
  6481                              <1> GET_PARM_N:
  6482                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6483 00002927 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6484                              <1> 	;PUSH	ES
  6485 00002928 53                  <1> 	PUSH	eBX
  6486                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6487                              <1> 	;MOV	DS,AX
  6488                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6489                              <1> 	;JZ	short G0
  6490                              <1> 	;LES	BX,@HF1_TBL_VEC
  6491                              <1> 	;JMP	SHORT G1
  6492                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6493                              <1> ;G1:
  6494                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6495                              <1> 	; 22/12/2014
  6496                              <1> 	;push	cs
  6497                              <1> 	;pop	ds
  6498 00002929 66BB1000            <1> 	mov	bx, KDATA
  6499 0000292D 8EDB                <1> 	mov	ds, bx
  6500                              <1> 	;mov	es, bx
  6501                              <1> 	;
  6502 0000292F 80EA80              <1> 	SUB	DL,80H
  6503 00002932 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6504 00002935 7340                <1> 	JAE	short G4
  6505                              <1> 	;
  6506 00002937 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6507                              <1> 	; 22/12/2014
  6508 00002939 88D3                <1> 	mov	bl, dl
  6509                              <1> 	;xor	bh, bh  
  6510 0000293B C0E302              <1> 	shl	bl, 2			; convert index to offset
  6511                              <1> 	;add	bx, HF_TBL_VEC
  6512 0000293E 81C3[246D0000]      <1> 	add	ebx, HF_TBL_VEC
  6513                              <1> 	;mov	ax, [bx+2]
  6514                              <1> 	;mov	es, ax			; dpt segment
  6515                              <1> 	;mov	bx, [bx]		; dpt offset
  6516 00002944 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6517                              <1> 
  6518 00002946 C605[1F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6519                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6520 0000294D 668B03              <1> 	mov	ax, [ebx]
  6521                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6522 00002950 6648                <1> 	dec	ax			; max. cylinder number
  6523 00002952 88C5                <1> 	MOV	CH,AL
  6524 00002954 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6525 00002958 66D1E8              <1> 	SHR	AX,1
  6526 0000295B 66D1E8              <1> 	SHR	AX,1
  6527                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6528 0000295E 0A430E              <1> 	or	al, [ebx+14]
  6529 00002961 88C1                <1> 	MOV	CL,AL
  6530                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6531 00002963 8A7302              <1> 	mov	dh, [ebx+2]
  6532 00002966 FECE                <1> 	DEC	DH			; 0-N RANGE
  6533 00002968 8A15[206D0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6534                              <1> 	;SUB	AX,AX
  6535                              <1> 	; 24/12/2021
  6536 0000296E 29C0                <1> 	sub	eax, eax
  6537                              <1> 	; 27/12/2014 
  6538                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6539                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6540                              <1> 	;mov	di, bx			; HDPT offset
  6541 00002970 89DF                <1> 	mov	edi, ebx
  6542                              <1> G5:
  6543 00002972 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6544                              <1> 	;POP	ES
  6545 00002973 1F                  <1> 	POP	DS
  6546                              <1> 	;RETf	2
  6547 00002974 CA0400              <1> 	retf	4
  6548                              <1> G4:
  6549 00002977 C605[1F6D0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6550                              <1> 	; 24/12/2021
  6551 0000297E 29C0                <1> 	sub	eax, eax
  6552 00002980 B407                <1> 	MOV	AH,INIT_FAIL
  6553                              <1> 	;SUB	AL,AL
  6554                              <1> 	;SUB	DX,DX
  6555 00002982 29D2                <1> 	sub	edx, edx
  6556                              <1> 	;SUB	CX,CX
  6557 00002984 29C9                <1> 	sub	ecx, ecx
  6558 00002986 F9                  <1> 	STC				; SET ERROR FLAG
  6559 00002987 EBE9                <1> 	JMP	short G5
  6560                              <1> 
  6561                              <1> ;----------------------------------------
  6562                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6563                              <1> ;----------------------------------------
  6564                              <1> 	; 03/01/2015
  6565                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6566                              <1> 	; logical sector per logical track
  6567                              <1> 	; and logical heads - 1 would be set but
  6568                              <1> 	; it is seen as it will be good
  6569                              <1> 	; if physical parameters will be set here
  6570                              <1> 	; because, number of heads <= 16.
  6571                              <1> 	; (logical heads usually more than 16)
  6572                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6573                              <1> 	;	== INT 13h physical parameters
  6574                              <1> 
  6575                              <1> ;INIT_DRV:
  6576                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6577                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6578                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6579                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6580                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6581                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6582                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6583                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6584                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6585                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6586                              <1> ;	SUB	AX,AX
  6587                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6588                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6589                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6590                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6591                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6592                              <1> ;	CALL	CHECK_STATUS
  6593                              <1> ;INIT_EXIT:
  6594                              <1> ;	RETn
  6595                              <1> 
  6596                              <1> ; 04/01/2015
  6597                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6598                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6599                              <1> INIT_DRV:
  6600                              <1> 	;xor	ah,ah
  6601 00002989 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6602 0000298B B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6603 0000298D 3825[346D0000]      <1>         cmp     [LBAMode], ah   ; 0
  6604 00002993 7702                <1> 	ja	short idrv0
  6605 00002995 B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6606                              <1> idrv0:
  6607                              <1> 	; DL = drive number (0 based)
  6608 00002997 E8BB030000          <1> 	call	GET_VEC
  6609                              <1> 	;push	bx
  6610 0000299C 53                  <1> 	push	ebx ; 21/02/2015
  6611                              <1> 	;add	bx,ax
  6612 0000299D 01C3                <1> 	add	ebx,eax
  6613                              <1> 	;; 05/01/2015
  6614 0000299F 8A25[78670000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6615                              <1> 	;;and 	ah,1 
  6616 000029A5 C0E404              <1> 	shl	ah,4
  6617 000029A8 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6618                              <1> 	;mov	al,[es:bx]
  6619 000029AB 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6620 000029AD FEC8                <1> 	dec	al	 ; last head number 
  6621                              <1> 	;and	al,0Fh
  6622 000029AF 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6623                              <1> 	;
  6624 000029B1 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6625 000029B5 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6626                              <1> 	;pop	bx
  6627 000029B8 5B                  <1> 	pop	ebx
  6628 000029B9 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6629 000029BB B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6630 000029BD 803D[346D0000]00    <1> 	cmp	byte [LBAMode],0
  6631 000029C4 7702                <1> 	ja	short idrv1
  6632 000029C6 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6633                              <1> idrv1:
  6634                              <1> 	;xor	ah,ah
  6635                              <1> 	;add	bx,ax
  6636 000029C8 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6637                              <1> 	;mov	al,[es:bx]
  6638                              <1> 			; sector number
  6639 000029CA 8A03                <1> 	mov	al,[ebx]
  6640 000029CC 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6641 000029CF 28C0                <1> 	sub	al,al
  6642 000029D1 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6643 000029D4 E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6644 000029D9 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6645 000029DB E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6646 000029E0 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6647 000029E2 E8C3020000          <1> 	call	CHECK_STATUS
  6648                              <1> INIT_EXIT:
  6649 000029E7 C3                  <1> 	RETn
  6650                              <1> 
  6651                              <1> ;----------------------------------------
  6652                              <1> ;	READ LONG	     (AH = 0AH) :
  6653                              <1> ;----------------------------------------
  6654                              <1> 
  6655                              <1> RD_LONG:
  6656                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6657 000029E8 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6658 000029EC E9E0000000          <1>         JMP     COMMANDI
  6659                              <1> 
  6660                              <1> ;----------------------------------------
  6661                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6662                              <1> ;----------------------------------------
  6663                              <1> 
  6664                              <1> WR_LONG:
  6665                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6666 000029F1 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6667 000029F5 E92C010000          <1>         JMP     COMMANDO
  6668                              <1> 
  6669                              <1> ;----------------------------------------
  6670                              <1> ;	SEEK		     (AH = 0CH) :
  6671                              <1> ;----------------------------------------
  6672                              <1> 
  6673                              <1> DISK_SEEK:
  6674 000029FA C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6675 000029FE E89A010000          <1> 	CALL	COMMAND
  6676 00002A03 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6677 00002A05 E80C020000          <1> 	CALL	_WAIT
  6678 00002A0A 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6679 00002A0C E899020000          <1> 	CALL	CHECK_STATUS
  6680 00002A11 803D[1F6D0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6681 00002A18 7507                <1> 	JNE	short DS_EXIT
  6682 00002A1A C605[1F6D0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6683                              <1> DS_EXIT:
  6684 00002A21 C3                  <1> 	RETn
  6685                              <1> 
  6686                              <1> ;----------------------------------------
  6687                              <1> ;	TEST DISK READY      (AH = 10H) :
  6688                              <1> ;----------------------------------------
  6689                              <1> 
  6690                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6691 00002A22 E82B020000          <1> 	CALL	NOT_BUSY
  6692 00002A27 751C                <1> 	JNZ	short TR_EX
  6693 00002A29 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6694 00002A2C 668B15[74670000]    <1> 	MOV	DX,[HF_PORT]
  6695 00002A33 80C206              <1> 	add	dl,6
  6696 00002A36 EE                  <1> 	OUT	DX,AL
  6697 00002A37 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6698 00002A3C 7507                <1> 	JNZ	short TR_EX
  6699 00002A3E C605[1F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6700                              <1> TR_EX:	
  6701 00002A45 C3                  <1> 	RETn
  6702                              <1> 
  6703                              <1> ;----------------------------------------
  6704                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6705                              <1> ;----------------------------------------
  6706                              <1> 
  6707                              <1> HDISK_RECAL:
  6708 00002A46 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6709 00002A4A E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6710 00002A4F 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6711 00002A51 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6712 00002A56 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6713 00002A58 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6714 00002A5D 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6715                              <1> RECAL_X:
  6716 00002A5F E846020000          <1> 	CALL	CHECK_STATUS
  6717 00002A64 803D[1F6D0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6718 00002A6B 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6719 00002A6D C605[1F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6720                              <1> RECAL_EXIT:
  6721 00002A74 803D[1F6D0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6722 00002A7B C3                  <1> 	RETn
  6723                              <1> 
  6724                              <1> ;----------------------------------------
  6725                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6726                              <1> ;----------------------------------------
  6727                              <1> 
  6728                              <1> CTLR_DIAGNOSTIC:
  6729 00002A7C FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6730 00002A7D E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6731                              <1> 	;AND	AL,0BFH
  6732 00002A7F 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6733                              <1> 	;JMP	$+2
  6734                              <1> 	IODELAY
  2155 00002A81 EB00                <2>  jmp short $+2
  2156 00002A83 EB00                <2>  jmp short $+2
  6735 00002A85 E6A1                <1> 	OUT	INTB01,AL
  6736                              <1> 	IODELAY
  2155 00002A87 EB00                <2>  jmp short $+2
  2156 00002A89 EB00                <2>  jmp short $+2
  6737 00002A8B E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6738 00002A8D 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6739                              <1> 	;JMP	$+2
  6740                              <1> 	IODELAY
  2155 00002A8F EB00                <2>  jmp short $+2
  2156 00002A91 EB00                <2>  jmp short $+2
  6741 00002A93 E621                <1> 	OUT	INTA01,AL
  6742 00002A95 FB                  <1> 	STI
  6743 00002A96 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6744 00002A9B 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6745                              <1> 	;MOV	DX, HF_PORT+7
  6746 00002A9D 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  6747 00002AA4 80C207              <1> 	add	dl, 7
  6748 00002AA7 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6749 00002AA9 EE                  <1> 	OUT	DX,AL
  6750 00002AAA E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6751 00002AAF B480                <1> 	MOV	AH,TIME_OUT
  6752 00002AB1 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6753                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6754 00002AB3 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  6755 00002ABA FEC2                <1> 	inc	dl
  6756 00002ABC EC                  <1> 	IN	AL,DX
  6757 00002ABD A2[166D0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6758 00002AC2 B400                <1> 	MOV	AH,0
  6759 00002AC4 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6760 00002AC6 7402                <1> 	JE	SHORT CD_EXIT
  6761 00002AC8 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6762                              <1> CD_EXIT:
  6763 00002ACA 8825[1F6D0000]      <1> 	MOV	[DISK_STATUS1],AH
  6764 00002AD0 C3                  <1> 	RETn
  6765                              <1> 
  6766                              <1> ;----------------------------------------
  6767                              <1> ; COMMANDI				:
  6768                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6769                              <1> ;	NSECTOR RETURNS ZERO		:
  6770                              <1> ;----------------------------------------
  6771                              <1> COMMANDI:
  6772 00002AD1 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6773 00002AD6 724D                <1> 	JC	short CMD_ABORT
  6774                              <1> 	;MOV	DI,BX
  6775 00002AD8 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6776 00002ADA E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6777 00002ADF 7544                <1> 	JNZ	short CMD_ABORT
  6778                              <1> CMD_I1:
  6779 00002AE1 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6780 00002AE6 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6781                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6782 00002AE8 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6783                              <1> 	;MOV	DX,HF_PORT
  6784 00002AED 668B15[74670000]    <1> 	mov	dx,[HF_PORT]
  6785 00002AF4 FA                  <1> 	CLI
  6786 00002AF5 FC                  <1> 	CLD
  6787 00002AF6 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6788 00002AF9 FB                  <1> 	STI
  6789 00002AFA F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6790 00002AFE 7419                <1> 	JZ	CMD_I3
  6791 00002B00 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6792 00002B05 721E                <1> 	JC	short TM_OUT
  6793                              <1> 	;MOV	DX,HF_PORT
  6794 00002B07 668B15[74670000]    <1> 	mov	dx,[HF_PORT]
  6795                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6796 00002B0E B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6797 00002B13 EC                  <1> CMD_I2: IN	AL,DX
  6798                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6799 00002B14 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6800 00002B16 47                  <1> 	INC	eDI
  6801 00002B17 E2FA                <1> 	LOOP	CMD_I2
  6802 00002B19 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6803 00002B1E 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6804 00002B20 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6805 00002B23 75BC                <1> 	JNZ	SHORT CMD_I1
  6806                              <1> CMD_ABORT:
  6807 00002B25 C3                  <1> TM_OUT: RETn
  6808                              <1> 
  6809                              <1> ;----------------------------------------
  6810                              <1> ; COMMANDO				:
  6811                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6812                              <1> ;	NSECTOR RETURNS ZERO		:
  6813                              <1> ;----------------------------------------
  6814                              <1> COMMANDO:
  6815 00002B26 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6816 00002B2B 72F8                <1> 	JC	short CMD_ABORT
  6817 00002B2D 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6818 00002B2F E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6819 00002B34 75EF                <1> 	JNZ	short CMD_ABORT
  6820 00002B36 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6821 00002B3B 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6822                              <1> CMD_O1: ;PUSH	DS
  6823                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6824                              <1> 	;POP	DS
  6825                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6826                              <1> 	;MOV	DX,HF_PORT
  6827                              <1> 	; 01/02/2015
  6828 00002B3D 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  6829                              <1> 	;push	es
  6830                              <1> 	;pop	ds
  6831                              <1> 	;mov	cx, 256
  6832 00002B44 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6833 00002B49 FA                  <1> 	CLI
  6834 00002B4A FC                  <1> 	CLD
  6835 00002B4B F3666F              <1> 	REP	OUTSW
  6836 00002B4E FB                  <1> 	STI
  6837                              <1> 	;POP	DS			; RESTORE DS
  6838 00002B4F F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6839 00002B53 7419                <1> 	JZ	short CMD_O3
  6840 00002B55 E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6841 00002B5A 72C9                <1> 	JC	short TM_OUT
  6842                              <1> 	;MOV	DX,HF_PORT
  6843 00002B5C 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  6844                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6845 00002B63 B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6846                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6847 00002B68 8A06                <1> 	mov	al, [esi]
  6848 00002B6A EE                  <1> 	OUT	DX,AL
  6849 00002B6B 46                  <1> 	INC	eSI
  6850 00002B6C E2FA                <1> 	LOOP	CMD_O2
  6851                              <1> CMD_O3:
  6852 00002B6E E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6853 00002B73 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6854 00002B75 E830010000          <1> 	CALL	CHECK_STATUS
  6855 00002B7A 75A9                <1> 	JNZ	short CMD_ABORT
  6856 00002B7C F605[156D0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6857 00002B83 75B8                <1> 	JNZ	SHORT CMD_O1
  6858                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6859 00002B85 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  6860                              <1> 	;add	dl, 2
  6861 00002B8C FEC2                <1> 	inc	dl
  6862 00002B8E FEC2                <1> 	inc	dl
  6863 00002B90 EC                  <1> 	IN	AL,DX			;
  6864 00002B91 A8FF                <1> 	TEST	AL,0FFH 		;
  6865 00002B93 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6866 00002B95 C605[1F6D0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6867                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6868                              <1> CMD_O4:
  6869 00002B9C C3                  <1> 	RETn
  6870                              <1> 
  6871                              <1> ;--------------------------------------------------------
  6872                              <1> ; COMMAND						:
  6873                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6874                              <1> ; OUTPUT						:
  6875                              <1> ;	BL = STATUS					:
  6876                              <1> ;	BH = ERROR REGISTER				:
  6877                              <1> ;--------------------------------------------------------
  6878                              <1> 
  6879                              <1> COMMAND:
  6880 00002B9D 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6881                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6882                              <1> COMMAND1:
  6883                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6884 00002B9E E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6885                              <1> 	;;POP	CX
  6886 00002BA3 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6887 00002BA5 803D[1F6D0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6888                              <1> 	;JZ	short CMD_TIMEOUT
  6889                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6890                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6891 00002BAC 7507                <1> 	jne	short COMMAND4
  6892                              <1> CMD_TIMEOUT:
  6893 00002BAE C605[1F6D0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6894                              <1> COMMAND4:
  6895 00002BB5 5B                  <1> 	POP	eBX
  6896 00002BB6 803D[1F6D0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6897 00002BBD C3                  <1> 	RETn
  6898                              <1> COMMAND2:
  6899 00002BBE 5B                  <1> 	POP	eBX
  6900 00002BBF 57                  <1> 	PUSH	eDI
  6901 00002BC0 C605[176D0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6902 00002BC7 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6903 00002BC8 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6904                              <1> 	;AND	AL,0BFH
  6905 00002BCA 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6906                              <1> 	;JMP	$+2
  6907                              <1> 	IODELAY
  2155 00002BCC EB00                <2>  jmp short $+2
  2156 00002BCE EB00                <2>  jmp short $+2
  6908 00002BD0 E6A1                <1> 	OUT	INTB01,AL
  6909 00002BD2 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6910 00002BD4 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6911                              <1> 	;JMP	$+2
  6912                              <1> 	IODELAY
  2155 00002BD6 EB00                <2>  jmp short $+2
  2156 00002BD8 EB00                <2>  jmp short $+2
  6913 00002BDA E621                <1> 	OUT	INTA01,AL
  6914 00002BDC FB                  <1> 	STI
  6915 00002BDD 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6916                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6917 00002BDF 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  6918 00002BE6 FEC2                <1> 	inc	dl
  6919 00002BE8 F605[216D0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6920 00002BEF 7411                <1> 	JZ	short COMMAND3
  6921 00002BF1 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6922 00002BF4 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6923 00002BF6 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6924 00002BF8 7208                <1> 	JB	short COMMAND3
  6925 00002BFA 3C40                <1> 	CMP	AL,40H
  6926 00002BFC 7704                <1> 	JA	short COMMAND3
  6927 00002BFE 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6928                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6929                              <1> COMMAND3:
  6930 00002C02 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6931 00002C06 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6932                              <1> 	IODELAY
  2155 00002C07 EB00                <2>  jmp short $+2
  2156 00002C09 EB00                <2>  jmp short $+2
  6933 00002C0B 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6934 00002C0C 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6935 00002C0E 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6936 00002C12 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6937 00002C14 5F                  <1> 	POP	eDI
  6938 00002C15 C3                  <1> 	RETn				; ZERO FLAG IS SET
  6939                              <1> 
  6940                              <1> ;CMD_TIMEOUT:
  6941                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6942                              <1> ;COMMAND4:
  6943                              <1> ;	POP	BX
  6944                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6945                              <1> ;	RETn
  6946                              <1> 
  6947                              <1> ;----------------------------------------
  6948                              <1> ;	WAIT FOR INTERRUPT		:
  6949                              <1> ;----------------------------------------
  6950                              <1> ;WAIT:
  6951                              <1> _WAIT:
  6952 00002C16 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6953                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6954                              <1> 	;CLC
  6955                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6956                              <1> 	;INT	15H
  6957                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6958                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6959                              <1> 
  6960                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6961                              <1> 	;; 21/02/2015
  6962                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6963                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6964 00002C17 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6965                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6966                              <1> ;-----	WAIT LOOP
  6967                              <1> 
  6968                              <1> WT1:	
  6969                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6970 00002C1C F605[176D0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6971                              <1> 	;LOOPZ	WT1
  6972 00002C23 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6973                              <1> 	;DEC	BL
  6974                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6975                              <1> 
  6976                              <1> WT1_hi:
  6977 00002C25 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6978 00002C27 A810                <1> 	test	al, 10h			; transition on memory
  6979 00002C29 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6980                              <1> WT1_lo:
  6981 00002C2B E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6982 00002C2D A810                <1> 	test	al, 10h			
  6983 00002C2F 74FA                <1> 	jz	short WT1_lo
  6984 00002C31 E2E9                <1> 	loop	WT1
  6985                              <1> 	;;or	bl, bl
  6986                              <1> 	;;jz	short WT2	
  6987                              <1> 	;;dec	bl
  6988                              <1> 	;;jmp	short WT1
  6989                              <1> 	;dec	bl
  6990                              <1> 	;jnz	short WT1	
  6991                              <1> 
  6992 00002C33 C605[1F6D0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6993 00002C3A EB0E                <1> 	JMP	SHORT WT4
  6994 00002C3C C605[1F6D0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6995 00002C43 C605[176D0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6996 00002C4A 803D[1F6D0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6997 00002C51 C3                  <1> 	RETn
  6998                              <1> 
  6999                              <1> ;----------------------------------------
  7000                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  7001                              <1> ;----------------------------------------
  7002                              <1> NOT_BUSY:
  7003 00002C52 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  7004                              <1> 	;PUSH	eBX
  7005                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  7006 00002C53 668B15[74670000]    <1> 	mov	DX, [HF_PORT]
  7007 00002C5A 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  7008                              <1> 	;MOV	BL,DELAY_1
  7009                              <1> 					; wait for 10 seconds
  7010                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  7011                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  7012                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  7013 00002C5D B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  7014                              <1> 	;
  7015                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  7016                              <1> NB1:	
  7017 00002C62 EC                  <1> 	IN	AL,DX			; CHECK STATUS
  7018                              <1> 	;TEST	AL,ST_BUSY
  7019 00002C63 2480                <1> 	and	al, ST_BUSY
  7020                              <1> 	;LOOPNZ	NB1
  7021 00002C65 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  7022                              <1> 	;DEC	BL			
  7023                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  7024                              <1> 
  7025 00002C67 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7026 00002C69 A810                <1> 	TEST	AL,010H			; transition on memory
  7027 00002C6B 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7028 00002C6D E461                <1> NB1_lo: IN	AL,SYS1
  7029 00002C6F A810                <1> 	TEST	AL,010H
  7030 00002C71 74FA                <1> 	JZ	short NB1_lo
  7031 00002C73 E2ED                <1> 	LOOP	NB1
  7032                              <1> 	;dec	bl
  7033                              <1> 	;jnz	short NB1
  7034                              <1> 	;
  7035                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7036                              <1> ;;	jb	short NB1
  7037                              <1> 	;
  7038                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7039                              <1> 	;JMP	SHORT NB3
  7040 00002C75 B080                <1> 	mov	al, TIME_OUT
  7041                              <1> NB2:	
  7042                              <1> 	;MOV	byte [DISK_STATUS1],0
  7043                              <1> ;NB3:	
  7044                              <1> 	;POP	eBX
  7045 00002C77 A2[1F6D0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7046                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7047 00002C7C 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7048 00002C7E C3                  <1> 	RETn
  7049                              <1> 
  7050                              <1> ;----------------------------------------
  7051                              <1> ;	WAIT FOR DATA REQUEST		:
  7052                              <1> ;----------------------------------------
  7053                              <1> WAIT_DRQ:
  7054                              <1> 	;MOV	CX,DELAY_3
  7055                              <1> 	;MOV	DX,HF_PORT+7
  7056 00002C7F 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  7057 00002C86 80C207              <1> 	add	dl, 7
  7058                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7059                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7060                              <1> 					; (but it is written as 2000
  7061                              <1> 					; micro seconds in ATORGS.ASM file
  7062                              <1> 					; of Award Bios - 1999, D1A0622)
  7063 00002C89 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7064 00002C8E EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7065 00002C8F A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7066 00002C91 7516                <1> 	JNZ	short WQ_OK
  7067                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7068                              <1> WQ_hi:	
  7069 00002C93 E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7070 00002C95 A810                <1> 	TEST	AL,010H			; transition on memory
  7071 00002C97 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7072 00002C99 E461                <1> WQ_lo:  IN      AL,SYS1
  7073 00002C9B A810                <1> 	TEST	AL,010H
  7074 00002C9D 74FA                <1> 	JZ	SHORT WQ_lo
  7075 00002C9F E2ED                <1> 	LOOP	WQ_1
  7076                              <1> 
  7077 00002CA1 C605[1F6D0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7078 00002CA8 F9                  <1> 	STC
  7079                              <1> WQ_OK:
  7080 00002CA9 C3                  <1> 	RETn
  7081                              <1> ;WQ_OK:	;CLC
  7082                              <1> ;	RETn
  7083                              <1> 
  7084                              <1> ;----------------------------------------
  7085                              <1> ;	CHECK FIXED DISK STATUS 	:
  7086                              <1> ;----------------------------------------
  7087                              <1> CHECK_STATUS:
  7088 00002CAA E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7089 00002CAF 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7090 00002CB1 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7091 00002CB3 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7092 00002CB5 E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7093                              <1> CHECK_S1:
  7094 00002CBA 803D[1F6D0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7095 00002CC1 C3                  <1> 	RETn
  7096                              <1> 
  7097                              <1> ;----------------------------------------
  7098                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7099                              <1> ;----------------------------------------
  7100                              <1> CHECK_ST:
  7101                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7102 00002CC2 668B15[74670000]    <1> 	mov	dx, [HF_PORT]
  7103 00002CC9 80C207              <1> 	add	dl, 7
  7104 00002CCC EC                  <1> 	IN	AL,DX
  7105 00002CCD A2[156D0000]        <1> 	MOV	[HF_STATUS],AL
  7106 00002CD2 B400                <1> 	MOV	AH,0
  7107 00002CD4 A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7108 00002CD6 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7109 00002CD8 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7110 00002CDA A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7111 00002CDC 7514                <1> 	JNZ	short CKST_EXIT
  7112 00002CDE B4AA                <1> 	MOV	AH,NOT_RDY
  7113 00002CE0 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7114 00002CE2 740E                <1> 	JZ	short CKST_EXIT
  7115 00002CE4 B440                <1> 	MOV	AH,BAD_SEEK
  7116 00002CE6 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7117 00002CE8 7408                <1> 	JZ	short CKST_EXIT
  7118 00002CEA B411                <1> 	MOV	AH,DATA_CORRECTED
  7119 00002CEC A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7120 00002CEE 7502                <1> 	JNZ	short CKST_EXIT
  7121 00002CF0 B400                <1> 	MOV	AH,0
  7122                              <1> CKST_EXIT:
  7123 00002CF2 8825[1F6D0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7124 00002CF8 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7125 00002CFB 7403                <1> 	JZ	short CKST_EX1
  7126 00002CFD 80FC00              <1> 	CMP	AH,0
  7127                              <1> CKST_EX1:
  7128 00002D00 C3                  <1> 	RETn
  7129                              <1> 
  7130                              <1> ;----------------------------------------
  7131                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7132                              <1> ;----------------------------------------
  7133                              <1> CHECK_ER:
  7134                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7135 00002D01 668B15[74670000]    <1> 	mov	dx, [HF_PORT]		;
  7136 00002D08 FEC2                <1> 	inc	dl
  7137 00002D0A EC                  <1> 	IN	AL,DX
  7138 00002D0B A2[166D0000]        <1> 	MOV	[HF_ERROR],AL
  7139 00002D10 53                  <1> 	PUSH	eBX ; 21/02/2015
  7140 00002D11 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7141 00002D16 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7142 00002D18 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7143 00002D1A E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7144 00002D1C BB[68670000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7145 00002D21 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7146                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7147                              <1> 	;mov	ah, [bx]
  7148 00002D23 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7149 00002D25 8825[1F6D0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7150 00002D2B 5B                  <1> 	POP	eBX
  7151 00002D2C 80FC00              <1> 	CMP	AH,0
  7152 00002D2F C3                  <1> 	RETn
  7153                              <1> 
  7154                              <1> ;--------------------------------------------------------
  7155                              <1> ; CHECK_DMA						:
  7156                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7157                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7158                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7159                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7160                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7161                              <1> ;  -ERROR OTHERWISE					:
  7162                              <1> ;--------------------------------------------------------
  7163                              <1> CHECK_DMA:
  7164                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7165                              <1> 	; 24/12/2021
  7166 00002D30 50                  <1> 	push	eax
  7167 00002D31 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7168 00002D35 F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7169 00002D39 7404                <1> 	JZ	short CKD1
  7170 00002D3B 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7171 00002D3F 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7172 00002D42 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7173 00002D44 7207                <1> 	JB	short CKDERR		; TOO MANY
  7174 00002D46 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7175 00002D48 7203                <1> 	JB	short CKDERR		; ERROR
  7176 00002D4A F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7177                              <1> 	;POP	AX
  7178                              <1> 	; 24/12/2021
  7179 00002D4B 58                  <1> 	pop	eax
  7180 00002D4C C3                  <1> 	RETn				; NORMAL RETURN
  7181 00002D4D F9                  <1> CKDERR: STC				; INDICATE ERROR
  7182 00002D4E C605[1F6D0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7183                              <1> 	;POP	AX
  7184                              <1> 	; 24/12/2021
  7185 00002D55 58                  <1> 	pop	eax	
  7186 00002D56 C3                  <1> 	RETn
  7187                              <1> 
  7188                              <1> ;----------------------------------------
  7189                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7190                              <1> ;----------------------------------------
  7191                              <1> 					
  7192                              <1> ; INPUT -> DL = 0 based drive number
  7193                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7194                              <1> 
  7195                              <1> GET_VEC:
  7196                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7197                              <1> 	;MOV	ES,AX
  7198                              <1> 	;TEST	DL,1
  7199                              <1> 	;JZ	short GV_0
  7200                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7201                              <1> ;	JMP	SHORT GV_EXIT
  7202                              <1> ;GV_0:
  7203                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7204                              <1> ;
  7205                              <1> 	;xor	bh, bh
  7206 00002D57 31DB                <1> 	xor	ebx, ebx
  7207 00002D59 88D3                <1> 	mov	bl, dl
  7208                              <1> 	;;02/01/2015
  7209                              <1> 	;;shl	bl, 1			; port address offset
  7210                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7211                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7212 00002D5B C0E302              <1> 	shl	bl, 2	;;
  7213                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7214 00002D5E 81C3[246D0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7215                              <1> 	;push	word [bx+2]		; dpt segment
  7216                              <1> 	;pop	es
  7217                              <1> 	;mov	bx, [bx]		; dpt offset
  7218 00002D64 8B1B                <1> 	mov	ebx, [ebx]		
  7219                              <1> ;GV_EXIT:
  7220 00002D66 C3                  <1> 	RETn
  7221                              <1> 
  7222                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7223                              <1> hdc1_int: ; 21/02/2015
  7224                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7225                              <1> ;								:
  7226                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7227                              <1> ;								:
  7228                              <1> ;----------------------------------------------------------------
  7229                              <1> 
  7230                              <1> ; 22/12/2014
  7231                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7232                              <1> ;	 '11/15/85'
  7233                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7234                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7235                              <1> 
  7236                              <1> ;int_76h:
  7237                              <1> HD_INT:
  7238                              <1> 	;push	ax
  7239                              <1> 	; 24/12/2021
  7240 00002D67 50                  <1> 	push	eax
  7241 00002D68 1E                  <1> 	push	ds
  7242                              <1> 	;CALL	DDS
  7243                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7244 00002D69 66B81000            <1> 	mov	ax, KDATA
  7245 00002D6D 8ED8                <1> 	mov 	ds, ax
  7246                              <1> 	;
  7247                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7248                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7249 00002D6F C605[176D0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7250                              <1> 	;
  7251                              <1> 	;push	dx
  7252                              <1> 	; 24/12/2021
  7253 00002D76 52                  <1> 	push	edx
  7254 00002D77 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7255                              <1> 					; Clear Controller
  7256                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7257 00002D7B EC                  <1> 	in	al, dx			;
  7258                              <1> 	;pop	dx
  7259                              <1> 	; 24/12/2021
  7260 00002D7C 5A                  <1> 	pop	edx
  7261                              <1> 	NEWIODELAY
  2160 00002D7D E6EB                <2>  out 0EBh,al
  7262                              <1> 	;
  7263 00002D7F B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7264 00002D81 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7265                              <1> 	;JMP	$+2			; WAIT
  7266                              <1> 	NEWIODELAY
  2160 00002D83 E6EB                <2>  out 0EBh,al
  7267 00002D85 E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7268 00002D87 1F                  <1> 	pop	ds
  7269                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7270                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7271                              <1> 	;INT	15H			;  INTERRUPT
  7272                              <1> irq15_iret: ; 25/02/2015
  7273                              <1> 	;pop	ax
  7274                              <1> 	; 24/12/2021
  7275 00002D88 58                  <1> 	pop	eax
  7276 00002D89 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7277                              <1> 
  7278                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7279                              <1> hdc2_int: ; 21/02/2015
  7280                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7281                              <1> ;								:
  7282                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7283                              <1> ;								:
  7284                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7285                              <1> 
  7286                              <1> ;int_77h:
  7287                              <1> HD1_INT:
  7288                              <1> 	;push	ax
  7289                              <1> 	; 24/12/2021
  7290 00002D8A 50                  <1> 	push	eax
  7291                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7292                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7293 00002D8B B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7294 00002D8D E6A0                <1> 	out	0A0h, al
  7295 00002D8F EB00                <1>         jmp short $+2
  7296 00002D91 EB00                <1> 	jmp short $+2
  7297 00002D93 E4A0                <1> 	in	al, 0A0h
  7298 00002D95 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7299 00002D97 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7300                              <1> 	;
  7301 00002D99 1E                  <1> 	push	ds
  7302                              <1> 	;CALL	DDS
  7303                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7304 00002D9A 66B81000            <1> 	mov	ax, KDATA
  7305 00002D9E 8ED8                <1> 	mov 	ds, ax
  7306                              <1> 	;
  7307                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7308                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7309 00002DA0 800D[176D0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7310                              <1> 	;
  7311                              <1> 	;push	dx
  7312                              <1> 	; 24/12/2021
  7313 00002DA7 52                  <1> 	push	edx
  7314 00002DA8 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7315                              <1> 					; Clear Controller (Award BIOS 1999)
  7316 00002DAC EBCD                <1> 	jmp	short Clear_IRQ1415
  7317                              <1> 
  7318                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7319                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7320                              <1> 
  7321                              <1> ;////////////////////////////////////////////////////////////////////
  7322                              <1> ;; END OF DISK I/O SYTEM ///
  2099                                  %include 'memory.inc'  ; 09/03/2015
  2100                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2101                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.1) - MEMORY.INC
  2102                              <1> ; Last Modification: 31/12/2021
  2103                              <1> ;
  2104                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2105                              <1> 
  2106                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2107                              <1> 
  2108                              <1> ;;04/11/2014 (unix386.s)	
  2109                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2110                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2111                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2112                              <1> ;;
  2113                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2114                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2115                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2116                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2117                              <1> 
  2118                              <1> ; 27/04/2015
  2119                              <1> ; 09/03/2015
  2120                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2121                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2122                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2123                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2124                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2125                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2126                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2127                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2128                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2129                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2130                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2131                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2132                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2133                              <1> SWP_DISK_READ_ERR 	   equ 40
  2134                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2135                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2136                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2137                              <1> SWP_DISK_WRITE_ERR         equ 44
  2138                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2139                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2140                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2141                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2142                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2143                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2144                              <1> 					; (Indicates that the page is not allocated
  2145                              <1> 					; for the process, it is a shared or system
  2146                              <1>                                         ; page, it must not be deallocated!)
  2147                              <1> ; 14/12/2020
  2148                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2149                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2150                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2151                              <1> 				; (Out of memory allocation table)	
  2152                              <1> ;
  2153                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2154                              <1> ;;
  2155                              <1> ;; 10/10/2014
  2156                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2157                              <1> ;;
  2158                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2159                              <1> ;;	(virtual address = physical address)
  2160                              <1> ;; KERNEL PAGE TABLES:
  2161                              <1> ;;	Kernel page directory and all page tables are
  2162                              <1> ;;	on memory as initialized, as equal to physical memory
  2163                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2164                              <1> ;;
  2165                              <1> ;;	what for: User pages may be swapped out, when accessing
  2166                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2167                              <1> ;;	kernel would have to swap it in! But it is also may be
  2168                              <1> ;;	in use by a user process. (In system/kernel mode
  2169                              <1> ;;	kernel can access all memory pages even if they are
  2170                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2171                              <1> ;;	cause conflicts.) 
  2172                              <1> ;;	
  2173                              <1> ;;	As result of these conditions,
  2174                              <1> ;;	all kernel pages must be initialized as equal to 
  2175                              <1> ;;	physical layout for preventing page faults. 
  2176                              <1> ;;	Also, calling "allocate page" procedure after
  2177                              <1> ;;	a page fault can cause another page fault (double fault)
  2178                              <1> ;;	if all kernel page tables would not be initialized.
  2179                              <1> ;;
  2180                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2181                              <1> ;;	memory allocation table. (double word aligned)
  2182                              <1> ;;
  2183                              <1> ;;	[next_page] = first/next free space to be searched
  2184                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2185                              <1> ;;
  2186                              <1> ;;	[last_page] = End of memory (users space), as offset
  2187                              <1> ;;	to memory allocation table. (double word aligned)
  2188                              <1> ;;
  2189                              <1> ;; USER PAGE TABLES:
  2190                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2191                              <1> ;;		'ready only' marked copies of the 
  2192                              <1> ;;		parent process's page table entries (for
  2193                              <1> ;;		same physical memory).
  2194                              <1> ;;		(A page will be copied to a new page after
  2195                              <1> ;;		 if it causes R/W page fault.)
  2196                              <1> ;;
  2197                              <1> ;;	Every user process has own (different)
  2198                              <1> ;;	page directory and page tables.	
  2199                              <1> ;;
  2200                              <1> ;;	Code starts at virtual address 0, always.
  2201                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2202                              <1> ;;	(Programs can be written/developed as simple
  2203                              <1> ;;	 flat memory programs.)
  2204                              <1> ;;
  2205                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2206                              <1> ;;	Memory page will be allocated by kernel only 
  2207                              <1> ;;		(in kernel/system mode only).
  2208                              <1> ;;	* After a
  2209                              <1> ;;	  - 'not present' page fault
  2210                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2211                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2212                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2213                              <1> ;;	  request by running process.
  2214                              <1> ;;	* While creating a process, allocating a new buffer,
  2215                              <1> ;;	  new page tables etc.
  2216                              <1> ;;
  2217                              <1> ;;	At first,
  2218                              <1> ;;	- 'allocate page' procedure will be called;
  2219                              <1> ;,	   if it will return with a valid (>0) physical address
  2220                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2221                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2222                              <1> ;;	- 'allocate page' will be called for allocating page
  2223                              <1> ;;	   directory, page table and running space (data/code).
  2224                              <1> ;;	- every successful 'allocate page' call will decrease
  2225                              <1> ;;	  'free_pages' count (pointer).
  2226                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2227                              <1> ;;	  if 'free_pages' points to a ZERO.
  2228                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2229                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2230                              <1> ;;	  error except errors caused by attribute conflicts.
  2231                              <1> ;;	 (swapper functions)	 
  2232                              <1> ;;					
  2233                              <1> ;;	At second,
  2234                              <1> ;;	- page directory entry will be updated then page table
  2235                              <1> ;;	  entry will be updated.		
  2236                              <1> ;;
  2237                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2238                              <1> ;;	- M.A.T. has a size according to available memory as
  2239                              <1> ;;	  follows:
  2240                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2241                              <1> ;;		  - a bit with value of 0 means allocated page
  2242                              <1> ;;		  - a bit with value of 1 means a free page
  2243                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2244                              <1> ;;	  depending on M.A.T.
  2245                              <1> ;;		(NOTE: Free page count will not be checked
  2246                              <1> ;;		again -on M.A.T.- after initialization. 
  2247                              <1> ;;		Kernel will trust on initial count.)
  2248                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2249                              <1> ;;	  and it will be increased by deallocation procedures.
  2250                              <1> ;;	
  2251                              <1> ;;	- Available memory will be calculated during
  2252                              <1> ;;	  the kernel's initialization stage (in real mode).
  2253                              <1> ;;	  Memory allocation table and kernel page tables 
  2254                              <1> ;;	  will be formatted/sized as result of available
  2255                              <1> ;;	  memory calculation before paging is enabled.
  2256                              <1> ;;
  2257                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2258                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2259                              <1> ;;	- Memory allocation for kernel page directory size 
  2260                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2261                              <1> ;;	  for page tables)
  2262                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2263                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2264                              <1> ;;	- User (available) space will be started 
  2265                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2266                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2267                              <1> ;;	  memory allocation table and kernel's page directory
  2268                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2269                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2270                              <1> ;; 	  for buffers.
  2271                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2272                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2273                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2274                              <1> ;;
  2275                              <1> ;; For 1GB Available Memory:
  2276                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2277                              <1> ;;	- Memory allocation for kernel page directory size 
  2278                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2279                              <1> ;;	  for page tables)
  2280                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2281                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2282                              <1> ;;	- User (available) space will be started 
  2283                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2284                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2285                              <1> ;;	  memory allocation table and kernel's page directory
  2286                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2287                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2288                              <1> ;; 	  for buffers.
  2289                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2290                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2291                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2292                              <1> ;;
  2293                              <1> ;;
  2294                              <1> 
  2295                              <1> ;;************************************************************************************
  2296                              <1> ;; 
  2297                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2298                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2299                              <1> 
  2300                              <1> ;; Main factor: "sys fork" system call 
  2301                              <1> ;;	
  2302                              <1> ;; 		FORK
  2303                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2304                              <1> ;;  writable pages ---->|
  2305                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2306                              <1> ;; 
  2307                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2308                              <1> ;; 
  2309                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2310                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2311                              <1> ;;       -while R/W bit is 0-. 
  2312                              <1> ;; 
  2313                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2314                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2315                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2316                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2317                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2318                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2319                              <1> ;; 
  2320                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2321                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2322                              <1> ;;   Parent's PTE attributes are not changed.
  2323                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2324                              <1> ;;    destroy/mix previous fork result).
  2325                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2326                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2327                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2328                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2329                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2330                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2331                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2332                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2333                              <1> ;; 
  2334                              <1> ;; !? WHAT FOR (duplication after duplication):
  2335                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2336                              <1> ;; program/executable code continues from specified location as child process, 
  2337                              <1> ;; returns back previous code location as parent process, every child after 
  2338                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2339                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2340                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2341                              <1> ;; was copied to child's process segment (all of code and data) according to
  2342                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2343                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2344                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2345                              <1> ;; (complete running image of parent process) to the child process; 
  2346                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2347                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2348                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2349                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2350                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2351                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2352                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2353                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2354                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2355                              <1> ;; for sharing same read only pages between parent and child processes.
  2356                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2357                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2358                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2359                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2360                              <1> ;; -deallocation problem-.
  2361                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2362                              <1> ;; 
  2363                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2364                              <1> ;; # Page fault handler will do those:
  2365                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2366                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2367                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2368                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2369                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2370                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2371                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2372                              <1> ;;     to child process.)	
  2373                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2374                              <1> ;; # Page fault handler will do those:
  2375                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2376                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2377                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2378                              <1> ;;     address or not. 
  2379                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2380                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2381                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2382                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2383                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2384                              <1> ;; 
  2385                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2386                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2387                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2388                              <1> ;;       duplication method details, it is not possible multiple child processes
  2389                              <1> ;;       were using same page with duplicated PTEs.
  2390                              <1> ;; 
  2391                              <1> ;;************************************************************************************   
  2392                              <1> 
  2393                              <1> ;; 08/10/2014
  2394                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2395                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2396                              <1> 
  2397                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2398                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2399                              <1> ;; (25/08/2014, Revision: 5057) file 
  2400                              <1> ;; by KolibriOS Team (2004-2012)
  2401                              <1> 
  2402                              <1> allocate_page:
  2403                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2404                              <1> 	; 01/07/2015
  2405                              <1> 	; 05/05/2015
  2406                              <1> 	; 30/04/2015
  2407                              <1> 	; 16/10/2014
  2408                              <1> 	; 08/10/2014
  2409                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2410                              <1> 	;
  2411                              <1> 	; INPUT -> none
  2412                              <1> 	;
  2413                              <1> 	; OUTPUT ->
  2414                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2415                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2416                              <1> 	;
  2417                              <1> 	;	CF = 1 and EAX = 0 
  2418                              <1> 	; 		   if there is not a free page to be allocated	
  2419                              <1> 	;
  2420                              <1> 	; Modified Registers -> none (except EAX)
  2421                              <1> 	;
  2422 00002DAE A1[906C0000]        <1> 	mov	eax, [free_pages]
  2423 00002DB3 21C0                <1> 	and	eax, eax
  2424 00002DB5 7438                <1> 	jz	short out_of_memory
  2425                              <1> 	;
  2426 00002DB7 53                  <1> 	push	ebx
  2427 00002DB8 51                  <1> 	push	ecx
  2428                              <1> 	;
  2429 00002DB9 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2430 00002DBE 89D9                <1> 	mov	ecx, ebx
  2431                              <1>  				     ; NOTE: 32 (first_page) is initial
  2432                              <1> 				     ; value of [next_page].
  2433                              <1> 				     ; It points to the first available
  2434                              <1> 				     ; page block for users (ring 3) ...	
  2435                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2436                              <1> 				     ; (at the of the first 4 MB)		
  2437 00002DC0 031D[946C0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2438                              <1> 				 ; next_free_page >> 5
  2439 00002DC6 030D[986C0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2440                              <1> 				 ; (total_pages - 1) >> 5
  2441                              <1> al_p_scan:
  2442 00002DCC 39CB                <1> 	cmp	ebx, ecx
  2443 00002DCE 770A                <1> 	ja	short al_p_notfound
  2444                              <1> 	;
  2445                              <1> 	; 01/07/2015
  2446                              <1> 	; AMD64 Architecture Programmers Manual
  2447                              <1> 	; Volume 3:
  2448                              <1> 	; General-Purpose and System Instructions
  2449                              <1> 	;
  2450                              <1> 	; BSF - Bit Scan Forward
  2451                              <1> 	;
  2452                              <1> 	;   Searches the value in a register or a memory location
  2453                              <1> 	;   (second operand) for the least-significant set bit. 
  2454                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2455                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2456                              <1> 	;   register (first operand). If the second operand contains 0, 
  2457                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2458                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2459                              <1> 	;   of the searched value
  2460                              <1> 	;
  2461 00002DD0 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2462                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2463                              <1> 			   ; loads the destination with an index to
  2464                              <1> 			   ; first set bit. (0 -> 31) 
  2465                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2466 00002DD3 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2467                              <1> 			 ;
  2468                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2469                              <1> 			 ;	  with value of 1 means 
  2470                              <1> 			 ;	  the corresponding page is free 
  2471                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2472 00002DD5 83C304              <1> 	add	ebx, 4
  2473                              <1> 			 ; We return back for searching next page block
  2474                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2475                              <1> 			 ;	 we always will find at least 1 free page here.
  2476 00002DD8 EBF2                <1>         jmp     short al_p_scan
  2477                              <1> 	;
  2478                              <1> al_p_notfound:
  2479 00002DDA 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2480 00002DE0 890D[946C0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2481                              <1> 				 ; (deallocate_page procedure will change it)
  2482 00002DE6 31C0                <1> 	xor	eax, eax
  2483 00002DE8 A3[906C0000]        <1> 	mov	[free_pages], eax ; 0
  2484 00002DED 59                  <1> 	pop	ecx
  2485 00002DEE 5B                  <1> 	pop	ebx
  2486                              <1> 	;
  2487                              <1> ; 24/12/2021
  2488                              <1> ; ('swap_out' procedure call is disabled)
  2489                              <1> 
  2490                              <1> out_of_memory:
  2491                              <1> ;	call	swap_out
  2492                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2493                              <1> ;	;
  2494                              <1> ;	sub 	eax, eax ; 0
  2495 00002DEF F9                  <1> 	stc
  2496 00002DF0 C3                  <1> 	retn
  2497                              <1> 
  2498                              <1> al_p_found:
  2499 00002DF1 89D9                <1> 	mov	ecx, ebx
  2500 00002DF3 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2501 00002DF9 890D[946C0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2502                              <1> 				 ; address/offset (to the next)
  2503 00002DFF FF0D[906C0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2504                              <1> 	;
  2505 00002E05 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2506                              <1> 				 ; is copied into the Carry Flag and then cleared
  2507                              <1> 				 ; in the destination.
  2508                              <1> 				 ;
  2509                              <1> 				 ; Reset the bit which is corresponding to the 
  2510                              <1> 				 ; (just) allocated page.
  2511                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2512 00002E08 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2513 00002E0B 01C8                <1> 	add	eax, ecx	 ; = page number
  2514 00002E0D C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2515                              <1> 	; EAX = physical address of memory page
  2516                              <1> 	;
  2517                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2518                              <1> 	;       according to this EAX value...
  2519 00002E10 59                  <1> 	pop	ecx
  2520 00002E11 5B                  <1> 	pop	ebx
  2521                              <1> al_p_ok:
  2522 00002E12 C3                  <1> 	retn
  2523                              <1> 
  2524                              <1> make_page_dir:
  2525                              <1> 	; 18/04/2015
  2526                              <1> 	; 12/04/2015
  2527                              <1> 	; 23/10/2014
  2528                              <1> 	; 16/10/2014
  2529                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2530                              <1> 	;
  2531                              <1> 	; INPUT ->
  2532                              <1> 	;	none
  2533                              <1> 	; OUTPUT ->
  2534                              <1> 	;	(EAX = 0)
  2535                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2536                              <1> 	;	cf = 0 ->
  2537                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2538                              <1> 	;		  process/user.
  2539                              <1> 	;
  2540                              <1> 	; Modified Registers -> EAX
  2541                              <1> 	;
  2542 00002E13 E896FFFFFF          <1> 	call	allocate_page
  2543 00002E18 7216                <1> 	jc	short mkpd_error
  2544                              <1> 	;
  2545 00002E1A A3[A5700000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2546                              <1> 				  ; (Physical address)
  2547                              <1> clear_page:
  2548                              <1> 	; 18/04/2015
  2549                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2550                              <1> 	;
  2551                              <1> 	; INPUT ->
  2552                              <1> 	;	EAX = physical address of the page
  2553                              <1> 	; OUTPUT ->
  2554                              <1> 	;	all bytes of the page will be cleared
  2555                              <1> 	;
  2556                              <1> 	; Modified Registers -> none
  2557                              <1> 	;
  2558 00002E1F 57                  <1> 	push	edi
  2559 00002E20 51                  <1> 	push	ecx
  2560 00002E21 50                  <1> 	push	eax
  2561 00002E22 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2562 00002E27 89C7                <1> 	mov	edi, eax
  2563 00002E29 31C0                <1> 	xor	eax, eax
  2564 00002E2B F3AB                <1> 	rep	stosd
  2565 00002E2D 58                  <1> 	pop	eax
  2566 00002E2E 59                  <1> 	pop	ecx
  2567 00002E2F 5F                  <1> 	pop	edi
  2568                              <1> mkpd_error:
  2569                              <1> mkpt_error:
  2570 00002E30 C3                  <1> 	retn
  2571                              <1> 
  2572                              <1> make_page_table:
  2573                              <1> 	; 23/06/2015
  2574                              <1> 	; 18/04/2015
  2575                              <1> 	; 12/04/2015
  2576                              <1> 	; 16/10/2014
  2577                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2578                              <1> 	;
  2579                              <1> 	; INPUT ->
  2580                              <1> 	;	EBX = virtual (linear) address
  2581                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2582                              <1> 	;	      (higher 20 bits must be ZERO)
  2583                              <1> 	;	      (bit 0 must be 1)	 
  2584                              <1> 	;	u.pgdir = page directory (physical) address
  2585                              <1> 	; OUTPUT ->
  2586                              <1> 	;	EDX = Page directory entry address
  2587                              <1> 	;	EAX = Page table address
  2588                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2589                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2590                              <1> 	;
  2591                              <1> 	; Modified Registers -> EAX, EDX
  2592                              <1> 	;
  2593 00002E31 E878FFFFFF          <1> 	call	allocate_page
  2594 00002E36 72F8                <1> 	jc	short mkpt_error
  2595 00002E38 E811000000          <1> 	call	set_pde	
  2596 00002E3D EBE0                <1> 	jmp	short clear_page
  2597                              <1> 
  2598                              <1> make_page:
  2599                              <1> 	; 24/07/2015
  2600                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2601                              <1> 	;
  2602                              <1> 	; INPUT ->
  2603                              <1> 	;	EBX = virtual (linear) address
  2604                              <1> 	;	ECX = page attributes (lower 12 bits)
  2605                              <1> 	;	      (higher 20 bits must be ZERO)
  2606                              <1> 	;	      (bit 0 must be 1)	 
  2607                              <1> 	;	u.pgdir = page directory (physical) address
  2608                              <1> 	; OUTPUT ->
  2609                              <1> 	;	EBX = Virtual address
  2610                              <1> 	;	(EDX = PTE value)
  2611                              <1> 	;	EAX = Physical address
  2612                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2613                              <1> 	;
  2614                              <1> 	; Modified Registers -> EAX, EDX
  2615                              <1> 	;
  2616 00002E3F E86AFFFFFF          <1> 	call	allocate_page
  2617 00002E44 7207                <1> 	jc	short mkp_err
  2618 00002E46 E821000000          <1> 	call	set_pte	
  2619 00002E4B 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2620                              <1> mkp_err:
  2621 00002E4D C3                  <1> 	retn
  2622                              <1> 
  2623                              <1> set_pde:	; Set page directory entry (PDE)
  2624                              <1> 	; 20/07/2015
  2625                              <1> 	; 18/04/2015
  2626                              <1> 	; 12/04/2015
  2627                              <1> 	; 23/10/2014
  2628                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2629                              <1> 	;
  2630                              <1> 	; INPUT ->
  2631                              <1> 	;	EAX = physical address
  2632                              <1> 	;	      (use present value if EAX = 0)
  2633                              <1> 	;	EBX = virtual (linear) address
  2634                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2635                              <1> 	;	      (higher 20 bits must be ZERO)
  2636                              <1> 	;	      (bit 0 must be 1)	 
  2637                              <1> 	;	u.pgdir = page directory (physical) address
  2638                              <1> 	; OUTPUT ->
  2639                              <1> 	;	EDX = PDE address
  2640                              <1> 	;	EAX = page table address (physical)
  2641                              <1> 	;	;(CF=1 -> Invalid page address)
  2642                              <1> 	;
  2643                              <1> 	; Modified Registers -> EDX
  2644                              <1> 	;
  2645 00002E4E 89DA                <1> 	mov	edx, ebx
  2646 00002E50 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2647 00002E53 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2648 00002E56 0315[A5700000]      <1> 	add	edx, [u.pgdir]
  2649                              <1> 	;
  2650 00002E5C 21C0                <1> 	and	eax, eax
  2651 00002E5E 7506                <1> 	jnz	short spde_1
  2652                              <1> 	;
  2653 00002E60 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2654                              <1> 	;test	al, 1
  2655                              <1> 	;jz	short spde_2
  2656 00002E62 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2657                              <1> spde_1:
  2658                              <1> 	;and	cx, 0FFFh
  2659 00002E66 8902                <1> 	mov	[edx], eax
  2660 00002E68 66090A              <1> 	or	[edx], cx
  2661 00002E6B C3                  <1> 	retn
  2662                              <1> ;spde_2: ; error
  2663                              <1> ;	stc
  2664                              <1> ;	retn
  2665                              <1> 
  2666                              <1> set_pte:	; Set page table entry (PTE)
  2667                              <1> 	; 24/07/2015
  2668                              <1> 	; 20/07/2015
  2669                              <1> 	; 23/06/2015
  2670                              <1> 	; 18/04/2015
  2671                              <1> 	; 12/04/2015
  2672                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2673                              <1> 	;
  2674                              <1> 	; INPUT ->
  2675                              <1> 	;	EAX = physical page address
  2676                              <1> 	;	      (use present value if EAX = 0)
  2677                              <1> 	;	EBX = virtual (linear) address
  2678                              <1> 	;	ECX = page attributes (lower 12 bits)
  2679                              <1> 	;	      (higher 20 bits must be ZERO)
  2680                              <1> 	;	      (bit 0 must be 1)	 
  2681                              <1> 	;	u.pgdir = page directory (physical) address
  2682                              <1> 	; OUTPUT ->
  2683                              <1> 	;	EAX = physical page address
  2684                              <1> 	;	(EDX = PTE value)
  2685                              <1> 	;	EBX = virtual address
  2686                              <1> 	;
  2687                              <1> 	;	CF = 1 -> error
  2688                              <1> 	;
  2689                              <1> 	; Modified Registers -> EAX, EDX
  2690                              <1> 	;
  2691 00002E6C 50                  <1> 	push	eax
  2692 00002E6D A1[A5700000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2693 00002E72 E837000000          <1> 	call 	get_pde
  2694                              <1> 		; EDX = PDE address
  2695                              <1> 		; EAX = PDE value
  2696 00002E77 5A                  <1> 	pop	edx ; physical page address
  2697 00002E78 722A                <1> 	jc	short spte_err ; PDE not present
  2698                              <1> 	;
  2699 00002E7A 53                  <1> 	push	ebx ; 24/07/2015
  2700 00002E7B 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2701                              <1> 			    ; EDX = PT address (physical)	
  2702 00002E7F C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2703 00002E82 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2704                              <1> 			 ; clear higher 10 bits (PD bits)
  2705 00002E88 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2706 00002E8B 01C3                <1> 	add	ebx, eax
  2707                              <1> 	;
  2708 00002E8D 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2709 00002E8F A801                <1> 	test	al, 1
  2710 00002E91 740C                <1> 	jz	short spte_0
  2711 00002E93 09D2                <1> 	or	edx, edx
  2712 00002E95 750F                <1> 	jnz	short spte_1
  2713 00002E97 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2714 00002E9B 89C2                <1> 	mov	edx, eax
  2715 00002E9D EB09                <1> 	jmp	short spte_2	
  2716                              <1> spte_0:
  2717                              <1> 	; If this PTE contains a swap (disk) address,
  2718                              <1> 	; it can be updated by using 'swap_in' procedure
  2719                              <1> 	; only!
  2720 00002E9F 21C0                <1> 	and	eax, eax
  2721 00002EA1 7403                <1> 	jz	short spte_1
  2722                              <1> 	; 24/07/2015
  2723                              <1> 	; swapped page ! (on disk)
  2724 00002EA3 5B                  <1> 	pop	ebx
  2725                              <1> spte_err:
  2726 00002EA4 F9                  <1> 	stc
  2727 00002EA5 C3                  <1> 	retn
  2728                              <1> spte_1: 
  2729 00002EA6 89D0                <1> 	mov	eax, edx
  2730                              <1> spte_2:
  2731 00002EA8 09CA                <1> 	or	edx, ecx
  2732                              <1> 	; 23/06/2015
  2733 00002EAA 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2734                              <1> 	; 24/07/2015
  2735 00002EAC 5B                  <1> 	pop	ebx
  2736 00002EAD C3                  <1> 	retn
  2737                              <1> 
  2738                              <1> get_pde:	; Get present value of the relevant PDE
  2739                              <1> 	; 20/07/2015
  2740                              <1> 	; 18/04/2015
  2741                              <1> 	; 12/04/2015
  2742                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2743                              <1> 	;
  2744                              <1> 	; INPUT ->
  2745                              <1> 	;	EBX = virtual (linear) address
  2746                              <1> 	;	EAX = page directory (physical) address
  2747                              <1> 	; OUTPUT ->
  2748                              <1> 	;	EDX = Page directory entry address
  2749                              <1> 	;	EAX = Page directory entry value
  2750                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2751                              <1> 	; Modified Registers -> EDX, EAX
  2752                              <1> 	;
  2753 00002EAE 89DA                <1> 	mov	edx, ebx
  2754 00002EB0 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2755 00002EB3 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2756 00002EB6 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2757 00002EB8 8B02                <1> 	mov	eax, [edx]
  2758 00002EBA A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2759 00002EBC 751F                <1> 	jnz	short gpte_retn
  2760 00002EBE F9                  <1> 	stc
  2761                              <1> gpde_retn:	
  2762 00002EBF C3                  <1> 	retn
  2763                              <1> 
  2764                              <1> get_pte:
  2765                              <1> 		; Get present value of the relevant PTE
  2766                              <1> 	; 29/07/2015
  2767                              <1> 	; 20/07/2015
  2768                              <1> 	; 18/04/2015
  2769                              <1> 	; 12/04/2015
  2770                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2771                              <1> 	;
  2772                              <1> 	; INPUT ->
  2773                              <1> 	;	EBX = virtual (linear) address
  2774                              <1> 	;	EAX = page directory (physical) address
  2775                              <1> 	; OUTPUT ->
  2776                              <1> 	;	EDX = Page table entry address (if CF=0)
  2777                              <1> 	;	      Page directory entry address (if CF=1)
  2778                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2779                              <1> 	;	EAX = Page table entry value (page address)
  2780                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2781                              <1> 	; Modified Registers -> EAX, EDX
  2782                              <1> 	;
  2783 00002EC0 E8E9FFFFFF          <1> 	call 	get_pde
  2784 00002EC5 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2785                              <1> 	;jnc	short gpte_1
  2786                              <1> 	;retn
  2787                              <1> ;gpte_1:
  2788 00002EC7 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2789 00002ECB 89DA                <1> 	mov	edx, ebx
  2790 00002ECD C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2791 00002ED0 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2792                              <1> 			 ; clear higher 10 bits (PD bits)
  2793 00002ED6 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2794 00002ED9 01C2                <1> 	add	edx, eax
  2795 00002EDB 8B02                <1> 	mov	eax, [edx]
  2796                              <1> gpte_retn:
  2797 00002EDD C3                  <1> 	retn
  2798                              <1> 
  2799                              <1> deallocate_page_dir:
  2800                              <1> 	; 15/09/2015
  2801                              <1> 	; 05/08/2015
  2802                              <1> 	; 30/04/2015
  2803                              <1> 	; 28/04/2015
  2804                              <1> 	; 17/10/2014
  2805                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2806                              <1> 	;
  2807                              <1> 	; INPUT ->
  2808                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2809                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2810                              <1> 	; OUTPUT ->
  2811                              <1> 	;	All of page tables in the page directory
  2812                              <1> 	;	and page dir's itself will be deallocated
  2813                              <1> 	;	except 'read only' duplicated pages (will be converted
  2814                              <1> 	;	to writable pages).
  2815                              <1> 	;
  2816                              <1> 	; Modified Registers -> EAX
  2817                              <1> 	;
  2818                              <1> 	;
  2819 00002EDE 56                  <1> 	push	esi
  2820 00002EDF 51                  <1> 	push	ecx
  2821 00002EE0 50                  <1> 	push	eax
  2822 00002EE1 89C6                <1> 	mov	esi, eax 
  2823 00002EE3 31C9                <1> 	xor	ecx, ecx
  2824                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2825                              <1> 	; it must not be deallocated
  2826 00002EE5 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2827                              <1> dapd_0:
  2828 00002EE7 AD                  <1> 	lodsd
  2829 00002EE8 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2830 00002EEA 7409                <1> 	jz	short dapd_1	
  2831 00002EEC 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2832 00002EF0 E812000000          <1> 	call	deallocate_page_table			
  2833                              <1> dapd_1:
  2834 00002EF5 41                  <1> 	inc	ecx ; page directory entry index
  2835 00002EF6 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2836 00002EFC 72E9                <1> 	jb	short dapd_0
  2837                              <1> dapd_2:
  2838 00002EFE 58                  <1> 	pop	eax
  2839 00002EFF E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2840 00002F04 59                  <1> 	pop	ecx
  2841 00002F05 5E                  <1> 	pop	esi
  2842 00002F06 C3                  <1> 	retn
  2843                              <1> 
  2844                              <1> deallocate_page_table:
  2845                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2846                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2847                              <1> 	; 19/09/2015
  2848                              <1> 	; 15/09/2015
  2849                              <1> 	; 05/08/2015
  2850                              <1> 	; 30/04/2015
  2851                              <1> 	; 28/04/2015
  2852                              <1> 	; 24/10/2014
  2853                              <1> 	; 23/10/2014
  2854                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2855                              <1> 	;
  2856                              <1> 	; INPUT ->
  2857                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2858                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2859                              <1> 	;	(ECX = page directory entry index)
  2860                              <1> 	; OUTPUT ->
  2861                              <1> 	;	All of pages in the page table and page table's itself
  2862                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2863                              <1> 	;	(will be converted to writable pages).
  2864                              <1> 	;
  2865                              <1> 	; Modified Registers -> EAX
  2866                              <1> 	;
  2867 00002F07 56                  <1> 	push	esi
  2868 00002F08 57                  <1> 	push	edi
  2869 00002F09 52                  <1> 	push	edx
  2870 00002F0A 50                  <1> 	push	eax ; *
  2871 00002F0B 89C6                <1> 	mov	esi, eax 
  2872 00002F0D 31FF                <1> 	xor	edi, edi ; 0
  2873                              <1> dapt_0:
  2874 00002F0F AD                  <1> 	lodsd
  2875 00002F10 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2876 00002F12 7455                <1> 	jz	short dapt_1
  2877                              <1> 	;
  2878 00002F14 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2879                              <1> 				  ; (must be 1)
  2880 00002F16 753F                <1> 	jnz	short dapt_3
  2881                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2882 00002F18 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2883                              <1> 				   ; as child's page ?
  2884 00002F1C 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2885                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2886                              <1> 	; ECX = page directory entry index (0-1023)
  2887 00002F1E 53                  <1> 	push	ebx
  2888 00002F1F 51                  <1> 	push	ecx
  2889 00002F20 66C1E102            <1> 	shl	cx, 2 ; *4 
  2890 00002F24 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2891 00002F26 8B0B                <1> 	mov	ecx, [ebx]
  2892 00002F28 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2893 00002F2B 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2894 00002F2D 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2895                              <1> 	; EDI = page table entry index (0-1023)
  2896 00002F32 89FA                <1> 	mov	edx, edi 
  2897 00002F34 66C1E202            <1> 	shl	dx, 2 ; *4 
  2898 00002F38 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2899 00002F3A 8B1A                <1> 	mov	ebx, [edx]
  2900 00002F3C F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2901 00002F3F 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2902 00002F41 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2903 00002F45 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2904 00002F4A 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2905 00002F4C 7507                <1> 	jne	short dapt_2	; not same page
  2906                              <1> 				; deallocate the child's page
  2907 00002F4E 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2908 00002F51 59                  <1> 	pop	ecx
  2909 00002F52 5B                  <1> 	pop	ebx
  2910 00002F53 EB0D                <1> 	jmp	short dapt_4
  2911                              <1> 
  2912                              <1> ; 24/12/2021
  2913                              <1> ; ('dapt_1' is disabled)
  2914                              <1> ;
  2915                              <1> ;dapt_1:
  2916                              <1> ;	or	eax, eax	; swapped page ?
  2917                              <1> ;	jz	short dapt_5	; no
  2918                              <1> ;				; yes
  2919                              <1> ;	shr	eax, 1
  2920                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2921                              <1> ;				  ; on the swap disk (or in file)
  2922                              <1> ;	jmp	short dapt_5
  2923                              <1> dapt_2:
  2924 00002F55 59                  <1> 	pop	ecx
  2925 00002F56 5B                  <1> 	pop	ebx
  2926                              <1> dapt_3:	
  2927                              <1> 	; 12/07/2016
  2928 00002F57 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2929 00002F5B 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2930                              <1> 	;
  2931                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2932 00002F5D E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2933                              <1> dapt_4:
  2934 00002F62 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2935                              <1> dapt_1:	; 24/12/2021
  2936                              <1> dapt_5:
  2937 00002F69 47                  <1> 	inc	edi ; page table entry index
  2938 00002F6A 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2939 00002F70 729D                <1> 	jb	short dapt_0
  2940                              <1> 	;
  2941 00002F72 58                  <1> 	pop	eax ; *
  2942 00002F73 5A                  <1> 	pop	edx
  2943 00002F74 5F                  <1> 	pop	edi	
  2944 00002F75 5E                  <1> 	pop	esi
  2945                              <1> 	;
  2946                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2947                              <1> 	;retn
  2948                              <1> 
  2949                              <1> deallocate_page:
  2950                              <1> 	; 15/09/2015
  2951                              <1> 	; 28/04/2015
  2952                              <1> 	; 10/03/2015
  2953                              <1> 	; 17/10/2014
  2954                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2955                              <1> 	;
  2956                              <1> 	; INPUT -> 
  2957                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2958                              <1> 	; OUTPUT ->
  2959                              <1> 	;	[free_pages] is increased
  2960                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2961                              <1> 	;	CF = 1 if the page is already deallocated
  2962                              <1> 	; 	       (or not allocated) before.  
  2963                              <1> 	;
  2964                              <1> 	; Modified Registers -> EAX
  2965                              <1> 	;
  2966 00002F76 53                  <1> 	push	ebx
  2967 00002F77 52                  <1> 	push	edx
  2968                              <1> 	;
  2969 00002F78 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2970                              <1> 				     ; 12 bits right
  2971                              <1> 				     ; to get page number
  2972 00002F7B 89C2                <1> 	mov	edx, eax
  2973                              <1> 	; 15/09/2015
  2974 00002F7D C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2975                              <1> 				     ; (1 allocation bit = 1 page)
  2976                              <1> 				     ; (1 allocation bytes = 8 pages)
  2977 00002F80 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2978                              <1> 				     ; (to get 32 bit position)			
  2979                              <1> 	;
  2980 00002F83 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2981 00002F88 01D3                <1> 	add	ebx, edx
  2982 00002F8A 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2983                              <1> 				     ; (allocation bit position)	 
  2984 00002F8D 3B15[946C0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2985                              <1> 				     ; than the address in 'next_page' ?
  2986                              <1> 				     ; (next/first free page value)		
  2987 00002F93 7306                <1> 	jnb	short dap_1	     ; no	
  2988 00002F95 8915[946C0000]      <1> 	mov	[next_page], edx     ; yes
  2989                              <1> dap_1:
  2990 00002F9B 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2991                              <1> 				     ; set relevant bit to 1.
  2992                              <1> 				     ; set CF to the previous bit value	
  2993                              <1> 	;cmc			     ; complement carry flag	
  2994                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2995                              <1> 				     ; if the page is already deallocated
  2996                              <1> 				     ; before.	
  2997 00002F9E FF05[906C0000]      <1>         inc     dword [free_pages]
  2998                              <1> dap_2:
  2999 00002FA4 5A                  <1> 	pop	edx
  3000 00002FA5 5B                  <1> 	pop	ebx
  3001 00002FA6 C3                  <1> 	retn
  3002                              <1> 
  3003                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3004                              <1> ;;                                                              ;;
  3005                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  3006                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  3007                              <1> ;;                                                              ;;
  3008                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3009                              <1> 
  3010                              <1> ;;$Revision: 5057 $
  3011                              <1> 
  3012                              <1> 
  3013                              <1> ;;align 4
  3014                              <1> ;;proc alloc_page
  3015                              <1> 
  3016                              <1> ;;        pushfd
  3017                              <1> ;;        cli
  3018                              <1> ;;        push    ebx
  3019                              <1> ;;;//-
  3020                              <1> ;;        cmp     [pg_data.pages_free], 1
  3021                              <1> ;;        jle     .out_of_memory
  3022                              <1> ;;;//-
  3023                              <1> ;;
  3024                              <1> ;;        mov     ebx, [page_start]
  3025                              <1> ;;        mov     ecx, [page_end]
  3026                              <1> ;;.l1:
  3027                              <1> ;;        bsf     eax, [ebx];
  3028                              <1> ;;        jnz     .found
  3029                              <1> ;;        add     ebx, 4
  3030                              <1> ;;        cmp     ebx, ecx
  3031                              <1> ;;        jb      .l1
  3032                              <1> ;;        pop     ebx
  3033                              <1> ;;        popfd
  3034                              <1> ;;        xor     eax, eax
  3035                              <1> ;;        ret
  3036                              <1> ;;.found:
  3037                              <1> ;;;//-
  3038                              <1> ;;        dec     [pg_data.pages_free]
  3039                              <1> ;;        jz      .out_of_memory
  3040                              <1> ;;;//-
  3041                              <1> ;;        btr     [ebx], eax
  3042                              <1> ;;        mov     [page_start], ebx
  3043                              <1> ;;        sub     ebx, sys_pgmap
  3044                              <1> ;;        lea     eax, [eax+ebx*8]
  3045                              <1> ;;        shl     eax, 12
  3046                              <1> ;;;//-       dec [pg_data.pages_free]
  3047                              <1> ;;        pop     ebx
  3048                              <1> ;;        popfd
  3049                              <1> ;;        ret
  3050                              <1> ;;;//-
  3051                              <1> ;;.out_of_memory:
  3052                              <1> ;;        mov     [pg_data.pages_free], 1
  3053                              <1> ;;        xor     eax, eax
  3054                              <1> ;;        pop     ebx
  3055                              <1> ;;        popfd
  3056                              <1> ;;        ret
  3057                              <1> ;;;//-
  3058                              <1> ;;endp
  3059                              <1> 
  3060                              <1> duplicate_page_dir:
  3061                              <1> 	; 21/09/2015
  3062                              <1> 	; 31/08/2015
  3063                              <1> 	; 20/07/2015
  3064                              <1> 	; 28/04/2015
  3065                              <1> 	; 27/04/2015
  3066                              <1> 	; 18/04/2015
  3067                              <1> 	; 12/04/2015
  3068                              <1> 	; 18/10/2014
  3069                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3070                              <1> 	;
  3071                              <1> 	; INPUT -> 
  3072                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3073                              <1> 	;		    page directory.
  3074                              <1> 	; OUTPUT ->
  3075                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3076                              <1> 	;	       page directory.
  3077                              <1> 	;	(New page directory with new page table entries.)
  3078                              <1> 	;	(New page tables with read only copies of the parent's
  3079                              <1> 	;	pages.)
  3080                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3081                              <1> 	;
  3082                              <1> 	; Modified Registers -> none (except EAX)
  3083                              <1> 	;
  3084 00002FA7 E802FEFFFF          <1> 	call	allocate_page
  3085 00002FAC 723E                <1> 	jc	short dpd_err
  3086                              <1> 	;
  3087 00002FAE 55                  <1> 	push	ebp ; 20/07/2015
  3088 00002FAF 56                  <1> 	push	esi
  3089 00002FB0 57                  <1> 	push	edi
  3090 00002FB1 53                  <1> 	push	ebx
  3091 00002FB2 51                  <1> 	push	ecx
  3092 00002FB3 8B35[A5700000]      <1> 	mov	esi, [u.pgdir]
  3093 00002FB9 89C7                <1> 	mov	edi, eax
  3094 00002FBB 50                  <1> 	push	eax ; save child's page directory address
  3095                              <1> 	; 31/08/2015
  3096                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3097                              <1> 	; (use same system space for all user page tables) 
  3098 00002FBC A5                  <1> 	movsd
  3099 00002FBD BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3100 00002FC2 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3101                              <1> dpd_0:	
  3102 00002FC7 AD                  <1> 	lodsd
  3103                              <1> 	;or	eax, eax
  3104                              <1>         ;jnz     short dpd_1
  3105 00002FC8 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3106 00002FCA 7508                <1> 	jnz	short dpd_1
  3107                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3108 00002FCC 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3109 00002FD2 EB0F                <1> 	jmp	short dpd_2
  3110                              <1> dpd_1:	
  3111 00002FD4 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3112 00002FD8 89C3                <1> 	mov	ebx, eax
  3113                              <1> 	; EBX = Parent's page table address
  3114 00002FDA E81F000000          <1> 	call	duplicate_page_table
  3115 00002FDF 720C                <1> 	jc	short dpd_p_err
  3116                              <1> 	; EAX = Child's page table address
  3117 00002FE1 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3118                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3119                              <1> 			 ; (present, writable, user)
  3120                              <1> dpd_2:
  3121 00002FE3 AB                  <1> 	stosd
  3122 00002FE4 E2E1                <1> 	loop	dpd_0
  3123                              <1> 	;
  3124 00002FE6 58                  <1> 	pop	eax  ; restore child's page directory address
  3125                              <1> dpd_3:
  3126 00002FE7 59                  <1> 	pop	ecx
  3127 00002FE8 5B                  <1> 	pop	ebx
  3128 00002FE9 5F                  <1> 	pop	edi
  3129 00002FEA 5E                  <1> 	pop	esi
  3130 00002FEB 5D                  <1> 	pop	ebp ; 20/07/2015
  3131                              <1> dpd_err:
  3132 00002FEC C3                  <1> 	retn
  3133                              <1> dpd_p_err:
  3134                              <1> 	; release the allocated pages missing (recover free space)
  3135 00002FED 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3136 00002FEE 8B1D[A5700000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3137 00002FF4 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3138 00002FF9 29C0                <1> 	sub	eax, eax ; 0
  3139 00002FFB F9                  <1> 	stc
  3140 00002FFC EBE9                <1> 	jmp	short dpd_3	
  3141                              <1> 
  3142                              <1> duplicate_page_table:
  3143                              <1> 	; 31/12/2021
  3144                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3145                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3146                              <1> 	; 21/09/2015
  3147                              <1> 	; 20/07/2015
  3148                              <1> 	; 05/05/2015
  3149                              <1> 	; 28/04/2015
  3150                              <1> 	; 27/04/2015
  3151                              <1> 	; 18/04/2015
  3152                              <1> 	; 18/10/2014
  3153                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3154                              <1> 	;
  3155                              <1> 	; INPUT -> 
  3156                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3157                              <1> 	;       20/02/2017		 
  3158                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3159                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3160                              <1> 	; OUTPUT ->
  3161                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3162                              <1> 	;	      (with 'read only' attribute of page table entries)
  3163                              <1> 	;	20/02/2017
  3164                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3165                              <1> 	;	
  3166                              <1> 	;	CF = 1 -> error 
  3167                              <1> 	;
  3168                              <1> 	; Modified Registers -> EBP (except EAX)
  3169                              <1> 	;
  3170 00002FFE E8ABFDFFFF          <1> 	call	allocate_page
  3171 00003003 725B                <1> 	jc	short dpt_err
  3172                              <1> 	;
  3173 00003005 50                  <1> 	push	eax ; *
  3174 00003006 56                  <1> 	push	esi
  3175 00003007 57                  <1> 	push	edi
  3176 00003008 52                  <1> 	push	edx
  3177 00003009 51                  <1> 	push	ecx
  3178                              <1> 	;
  3179 0000300A 89DE                <1> 	mov	esi, ebx
  3180 0000300C 89C7                <1> 	mov	edi, eax
  3181 0000300E 89C2                <1> 	mov	edx, eax
  3182 00003010 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3183                              <1> dpt_0:
  3184 00003016 AD                  <1> 	lodsd
  3185 00003017 21C0                <1> 	and	eax, eax
  3186 00003019 7435                <1> 	jz	short dpt_3
  3187 0000301B A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3188                              <1> 	; 24/12/2021
  3189 0000301D 7503                <1> 	jnz	short dpt_1
  3190                              <1> 	;jz	short dpt_p_err
  3191                              <1> 	; 31/12/2021
  3192 0000301F F9                  <1> 	stc
  3193 00003020 EB39                <1> 	jmp	short dpt_p_err
  3194                              <1> 
  3195                              <1> ; 24/12/2021
  3196                              <1> ; ('reload_page' procedure call is disabled)
  3197                              <1> ;
  3198                              <1> ;	; 20/07/2015
  3199                              <1> ;	; ebp = virtual (linear) address of the memory page
  3200                              <1> ;	call	reload_page ; 28/04/2015
  3201                              <1> ;	jc	short dpt_p_err
  3202                              <1> dpt_1:
  3203                              <1> 	; 21/09/2015
  3204 00003022 89C1                <1> 	mov	ecx, eax
  3205 00003024 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3206 00003028 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3207 0000302B 751A                <1> 	jnz	short dpt_2
  3208                              <1> 	; Read only (parent) page
  3209                              <1> 	; 	- there is a third process which uses this page -
  3210                              <1> 	; Allocate a new page for the child process
  3211 0000302D E87CFDFFFF          <1> 	call	allocate_page
  3212 00003032 7227                <1> 	jc	short dpt_p_err
  3213 00003034 57                  <1> 	push	edi
  3214 00003035 56                  <1> 	push	esi
  3215 00003036 89CE                <1> 	mov	esi, ecx
  3216 00003038 89C7                <1> 	mov	edi, eax
  3217 0000303A B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3218 0000303F F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3219 00003041 5E                  <1> 	pop	esi
  3220 00003042 5F                  <1> 	pop	edi
  3221                              <1> 	;
  3222                              <1> 
  3223                              <1> ; 24/12/2021
  3224                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3225                              <1> ; 
  3226                              <1> ;	push	ebx
  3227                              <1> ;	push	eax
  3228                              <1> ;	; 20/07/2015
  3229                              <1> ;	mov	ebx, ebp
  3230                              <1> ;	; ebx = virtual (linear) address of the memory page
  3231                              <1> ;	call	add_to_swap_queue
  3232                              <1> ;	pop	eax
  3233                              <1> ;	pop	ebx
  3234                              <1> 
  3235                              <1> 	; 21/09/2015
  3236 00003043 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3237                              <1> 		; user + writable + present page
  3238 00003045 EB09                <1> 	jmp	short dpt_3
  3239                              <1> dpt_2:
  3240                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3241 00003047 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3242                              <1> 		    ; (read only page!)
  3243 00003049 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3244 0000304C 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3245                              <1> dpt_3:
  3246 00003050 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3247                              <1> 	;
  3248 00003051 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3249                              <1> 	;
  3250 00003057 39D7                <1> 	cmp	edi, edx
  3251 00003059 72BB                <1> 	jb	short dpt_0
  3252                              <1> dpt_p_err:
  3253 0000305B 59                  <1> 	pop	ecx
  3254 0000305C 5A                  <1> 	pop	edx
  3255 0000305D 5F                  <1> 	pop	edi
  3256 0000305E 5E                  <1> 	pop	esi
  3257 0000305F 58                  <1> 	pop	eax ; *
  3258                              <1> dpt_err:
  3259 00003060 C3                  <1> 	retn
  3260                              <1> 
  3261                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3262                              <1> 	; 31/12/2021
  3263                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3264                              <1> 	; 21/09/2015
  3265                              <1> 	; 19/09/2015
  3266                              <1> 	; 17/09/2015
  3267                              <1> 	; 28/08/2015
  3268                              <1> 	; 20/07/2015
  3269                              <1> 	; 28/06/2015
  3270                              <1> 	; 03/05/2015
  3271                              <1> 	; 30/04/2015
  3272                              <1> 	; 18/04/2015
  3273                              <1> 	; 12/04/2015
  3274                              <1> 	; 30/10/2014
  3275                              <1> 	; 11/09/2014
  3276                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3277                              <1> 	;
  3278                              <1> 	; Note: This is not an interrupt/exception handler.
  3279                              <1> 	;	This is a 'page fault remedy' subroutine 
  3280                              <1> 	;	which will be called by standard/uniform
  3281                              <1> 	;	exception handler.
  3282                              <1> 	;
  3283                              <1> 	; INPUT -> 
  3284                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3285                              <1> 	;
  3286                              <1> 	;	cr2 = the virtual (linear) address 
  3287                              <1> 	;	      which has caused to page fault (19/09/2015)
  3288                              <1> 	;
  3289                              <1> 	; OUTPUT ->
  3290                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3291                              <1> 	;	EAX = 0 -> no error
  3292                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3293                              <1> 	;
  3294                              <1> 	; Modified Registers -> none (except EAX)
  3295                              <1> 	;	
  3296                              <1>         ;
  3297                              <1>         ; ERROR CODE:
  3298                              <1> 	;	 31  .....	4   3	2   1	0
  3299                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3300                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3301                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3302                              <1> 	;
  3303                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3304                              <1>     	;		a page-protection violation. When not set,
  3305                              <1> 	;		it was caused by a non-present page.
  3306                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3307                              <1> 	;		a page write. When not set, it was caused
  3308                              <1> 	;		by a page read.
  3309                              <1> 	; U : USER    -	When set, the page fault was caused 
  3310                              <1> 	;		while CPL = 3. 
  3311                              <1> 	;		This does not necessarily mean that
  3312                              <1> 	;		the page fault was a privilege violation.
  3313                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3314                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3315                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3316                              <1> 	;     FETCH	an instruction fetch
  3317                              <1> 	;
  3318                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3319                              <1> 	;  31               22                  12 11                    0
  3320                              <1> 	; +-------------------+-------------------+-----------------------+
  3321                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3322                              <1>        	; +-------------------+-------------------+-----------------------+
  3323                              <1> 	;
  3324                              <1> 
  3325                              <1> 	;; CR3 REGISTER (Control Register 3)
  3326                              <1> 	;  31                                   12             5 4 3 2   0
  3327                              <1> 	; +---------------------------------------+-------------+---+-----+
  3328                              <1>       	; |                                       |  		|P|P|     |
  3329                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3330                              <1>       	; |                                       | 		|D|T|     |
  3331                              <1>    	; +---------------------------------------+-------------+---+-----+
  3332                              <1> 	;
  3333                              <1> 	;	PWT    - WRITE THROUGH
  3334                              <1> 	;	PCD    - CACHE DISABLE		
  3335                              <1> 	;
  3336                              <1> 	;
  3337                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3338                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3339                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3340                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3341                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3342                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3343                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3344                              <1> 	;
  3345                              <1>         ;       P      - PRESENT
  3346                              <1>         ;       R/W    - READ/WRITE
  3347                              <1>         ;       U/S    - USER/SUPERVISOR
  3348                              <1> 	;	PWT    - WRITE THROUGH
  3349                              <1> 	;	PCD    - CACHE DISABLE	
  3350                              <1> 	;	A      - ACCESSED	
  3351                              <1>         ;       D      - DIRTY (IGNORED)
  3352                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3353                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3354                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3355                              <1> 	;
  3356                              <1> 	;
  3357                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3358                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3359                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3360                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3361                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3362                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3363                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3364                              <1> 	;
  3365                              <1>         ;       P      - PRESENT
  3366                              <1>         ;       R/W    - READ/WRITE
  3367                              <1>         ;       U/S    - USER/SUPERVISOR
  3368                              <1> 	;	PWT    - WRITE THROUGH
  3369                              <1> 	;	PCD    - CACHE DISABLE	
  3370                              <1> 	;	A      - ACCESSED	
  3371                              <1>         ;       D      - DIRTY
  3372                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3373                              <1> 	;	G      - GLOBAL	 
  3374                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3375                              <1> 	;
  3376                              <1> 	;
  3377                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3378                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3379                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3380                              <1>       	; |                                       |     | | | | | | |U|R| |
  3381                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3382                              <1>       	; |                                       |     | | | | | | |S|W| |
  3383                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3384                              <1> 	;
  3385                              <1>         ;       P      - PRESENT
  3386                              <1>         ;       R/W    - READ/WRITE
  3387                              <1>         ;       U/S    - USER/SUPERVISOR
  3388                              <1>         ;       D      - DIRTY
  3389                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3390                              <1> 	;
  3391                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3392                              <1> 	;
  3393                              <1> 	;
  3394                              <1> 	;; Invalid Page Table Entry
  3395                              <1> 	; 31                                                           1 0
  3396                              <1>       	; +-------------------------------------------------------------+-+
  3397                              <1>       	; |                                                             | |
  3398                              <1>       	; |                          AVAILABLE                          |0|
  3399                              <1>       	; |                                                             | |
  3400                              <1>       	; +-------------------------------------------------------------+-+
  3401                              <1> 	;
  3402                              <1> 
  3403 00003061 53                  <1> 	push	ebx
  3404 00003062 52                  <1> 	push	edx
  3405 00003063 51                  <1> 	push	ecx
  3406                              <1> 	;
  3407                              <1> 	; 21/09/2015 (debugging)
  3408 00003064 FF05[B5700000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3409 0000306A FF05[406D0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3410                              <1> 	; 28/06/2015
  3411                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3412 00003070 8A15[386D0000]      <1> 	mov	dl, [error_code]
  3413                              <1> 	;
  3414 00003076 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3415                              <1> 			; sign
  3416 00003079 7425                <1> 	jz	short pfh_alloc_np
  3417                              <1> 	; 
  3418                              <1> 	; If it is not a 'write on read only page' type page fault
  3419                              <1> 	; major page fault error with minor reason must be returned without 
  3420                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3421                              <1> 	; after return here!
  3422                              <1> 	; Page fault will be remedied, by copying page contents
  3423                              <1> 	; to newly allocated page with write permission;
  3424                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3425                              <1> 	; used for working with minimum possible memory usage. 
  3426                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3427                              <1> 	; process with 'read only' flag. If the child process attempts to
  3428                              <1> 	; write on these read only pages, page fault will be directed here
  3429                              <1> 	; for allocating a new page with same data/content. 
  3430                              <1> 	;
  3431                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3432                              <1> 	; will not force to separate CODE and DATA space 
  3433                              <1> 	; in a process/program... 
  3434                              <1> 	; CODE segment/section may contain DATA!
  3435                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3436                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3437                              <1> 	;	
  3438 0000307B F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3439                              <1> 			; sign
  3440 0000307E 7418                <1>         jz      pfh_p_err
  3441                              <1> 	; 31/08/2015
  3442 00003080 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3443                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3444 00003083 7413                <1>         jz	short pfh_pv_err
  3445                              <1> 	;
  3446                              <1> 	; make a new page and copy the parent's page content
  3447                              <1> 	; as the child's new page content
  3448                              <1> 	;
  3449 00003085 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3450                              <1> 			 ; which has caused to page fault
  3451 00003088 E87C000000          <1> 	call 	copy_page
  3452 0000308D 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3453                              <1> 	;
  3454 0000308F EB72                <1>         jmp     pfh_cpp_ok
  3455                              <1> 
  3456                              <1> 	; 31/12/2021 (short jump)
  3457                              <1> pfh_im_err:
  3458 00003091 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3459                              <1> 			; Major (Primary) Error: Page Fault
  3460                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3461 00003096 EB6D                <1> 	jmp	short pfh_err_retn
  3462                              <1> 
  3463                              <1> 	; 31/12/2021
  3464                              <1> pfh_p_err: ; 09/03/2015
  3465                              <1> pfh_pv_err:
  3466                              <1> 	; Page fault was caused by a protection-violation
  3467 00003098 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3468                              <1> 			; Major (Primary) Error: Page Fault
  3469                              <1> 			; Minor (Secondary) Error: Protection violation !
  3470 0000309D F9                  <1> 	stc
  3471 0000309E EB65                <1> 	jmp	short pfh_err_retn
  3472                              <1> 	
  3473                              <1> pfh_alloc_np:
  3474 000030A0 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3475 000030A5 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3476                              <1> pfh_chk_cpl:
  3477                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3478                              <1> 		; (Lower 12 bits are ZERO, because 
  3479                              <1> 		;	the address is on a page boundary)
  3480 000030A7 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3481 000030AA 7505                <1> 	jnz	short pfh_um
  3482                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3483 000030AC 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3484                              <1> 			 ; of the current/active page directory
  3485                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3486                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3487 000030AF EB06                <1> 	jmp	short pfh_get_pde
  3488                              <1> 	;
  3489                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3490 000030B1 8B1D[A5700000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3491                              <1> 			; Physical address of the USER's page directory
  3492                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3493                              <1> pfh_get_pde:
  3494 000030B7 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3495 000030BA 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3496                              <1> 			 ; which has been caused to page fault
  3497                              <1> 			 ;
  3498 000030BD C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3499 000030C0 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3500                              <1> 	;
  3501 000030C3 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3502 000030C5 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3503 000030C7 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3504 000030CA 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3505                              <1> 			  	  ; set/validate page directory entry
  3506 000030CC 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3507 000030D1 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3508 000030D3 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3509 000030D5 EB16                <1> 	jmp	short pfh_get_pte
  3510                              <1> pfh_set_pde:
  3511                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3512                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3513                              <1> 	;
  3514 000030D7 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3515 000030D9 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3516 000030DB 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3517 000030DD 89C3                <1> 	mov	ebx, eax
  3518 000030DF E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3519 000030E4 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3520                              <1> pfh_spde_1:
  3521                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3522 000030E6 89C1                <1> 	mov	ecx, eax
  3523 000030E8 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3524                              <1> pfh_get_pte:
  3525 000030ED 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3526                              <1> 			 ; which has been caused to page fault
  3527 000030F0 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3528 000030F2 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3529                              <1> 			 ; higher 20 bits of the page fault address 
  3530 000030F5 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3531 000030FA C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3532 000030FD 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3533                              <1> ; 24/12/2021
  3534                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3535                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3536                              <1> ; 24/12/2021
  3537                              <1> ; ('swap_in' procedure call has been disabled)
  3538                              <1> ;
  3539                              <1> ;	and	eax, eax
  3540                              <1> ;	jz	short pfh_gpte_1
  3541                              <1> ;	; 20/07/2015
  3542                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3543                              <1> ;	push	ebp ; 20/07/2015
  3544                              <1> ;	mov	ebp, cr2
  3545                              <1> ;		; ECX = physical address of the page table entry
  3546                              <1> ;		; EBX = Memory page address (physical!)
  3547                              <1> ;		; EAX = Swap disk (offset) address
  3548                              <1> ;		; EBP = virtual address (page fault address)
  3549                              <1> ;	call	swap_in
  3550                              <1> ;	pop	ebp
  3551                              <1> ;	jc      short pfh_err_retn
  3552                              <1> ;	xchg	ecx, ebx
  3553                              <1> ;		; EBX = physical address of the page table entry
  3554                              <1> ;		; ECX = new page
  3555                              <1> pfh_gpte_1:
  3556 000030FF 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3557 00003101 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3558                              <1> pfh_cpp_ok:
  3559                              <1> ; 24/12/2021
  3560                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3561                              <1> ;
  3562                              <1> ;	; 20/07/2015
  3563                              <1> ;	mov	ebx, cr2
  3564                              <1> ;	call 	add_to_swap_queue
  3565                              <1> 	;
  3566                              <1> 	; The new PTE (which contains the new page) will be added to 
  3567                              <1> 	; the swap queue, here. 
  3568                              <1> 	; (Later, if memory will become insufficient, 
  3569                              <1> 	; one page will be swapped out which is at the head of 
  3570                              <1> 	; the swap queue by using FIFO and access check methods.)
  3571                              <1> 	;
  3572 00003103 31C0                <1> 	xor	eax, eax  ; 0
  3573                              <1> 	;
  3574                              <1> pfh_err_retn:
  3575 00003105 59                  <1> 	pop	ecx
  3576 00003106 5A                  <1> 	pop	edx
  3577 00003107 5B                  <1> 	pop	ebx
  3578 00003108 C3                  <1> 	retn 
  3579                              <1> 	
  3580                              <1> copy_page:
  3581                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3582                              <1> 	; 16/04/2021
  3583                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3584                              <1> 	; 22/09/2015
  3585                              <1> 	; 21/09/2015
  3586                              <1> 	; 19/09/2015
  3587                              <1> 	; 07/09/2015
  3588                              <1> 	; 31/08/2015
  3589                              <1> 	; 20/07/2015
  3590                              <1> 	; 05/05/2015
  3591                              <1> 	; 03/05/2015
  3592                              <1> 	; 18/04/2015
  3593                              <1> 	; 12/04/2015
  3594                              <1> 	; 30/10/2014
  3595                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3596                              <1> 	;
  3597                              <1> 	; INPUT -> 
  3598                              <1> 	;	EBX = Virtual (linear) address of source page
  3599                              <1> 	;	     (Page fault address)
  3600                              <1> 	; OUTPUT ->
  3601                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3602                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3603                              <1> 	;	EAX = 0 (CF = 1) 
  3604                              <1> 	;		if there is not a free page to be allocated
  3605                              <1> 	;	(page content of the source page will be copied
  3606                              <1> 	;	onto the target/new page) 	
  3607                              <1> 	;
  3608                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3609                              <1> 	;
  3610                              <1> 
  3611                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3612                              <1> 	; INPUT: 
  3613                              <1> 	;	EBX = Virtual (linear) address of source page
  3614                              <1> 	;	     (Page fault address)
  3615                              <1> 	; OUTPUT:
  3616                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3617                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3618                              <1> 	;	EAX = 0 (CF = 1) 
  3619                              <1> 	;		if there is not a free page to be allocated
  3620                              <1> 	;	(page content of the source page will be copied
  3621                              <1> 	;	onto the target/new page) 	
  3622                              <1> 	;
  3623                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3624                              <1> 	
  3625 00003109 56                  <1> 	push	esi ; *
  3626 0000310A 57                  <1> 	push	edi ; **
  3627                              <1> 	; 16/04/2021
  3628                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3629                              <1> 	;push	ebx ; ***
  3630                              <1> 	;push	ecx ; ****
  3631 0000310B 31F6                <1> 	xor 	esi, esi
  3632 0000310D C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3633 00003110 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3634 00003112 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3635 00003115 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3636 00003118 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3637 0000311A 031D[A5700000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3638 00003120 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3639 00003122 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3640 00003126 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3641 00003128 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3642 0000312E 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3643 00003132 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3644                              <1> 	; 07/09/2015
  3645 00003134 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3646                              <1> 				     ; read only page as a child process?)	
  3647 00003139 7509                <1> 	jnz	short cpp_0 ; yes
  3648 0000313B 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3649 0000313D 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3650 00003142 EB32                <1> 	jmp	short cpp_1
  3651                              <1> cpp_0:
  3652 00003144 89FE                <1> 	mov	esi, edi
  3653 00003146 0335[A9700000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3654 0000314C 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3655 0000314E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3656 00003152 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3657 00003154 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3658 0000315A 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3659 0000315E 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3660 00003160 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3661                              <1> 	; 21/09/2015
  3662 00003162 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3663 00003164 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3664                              <1> 	;
  3665 00003168 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3666 0000316B 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3667                              <1> 	;
  3668 0000316D 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3669 00003172 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3670 00003174 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3671                              <1> 			    ; Convert child's page to writable page
  3672                              <1> cpp_1:
  3673 00003176 E833FCFFFF          <1> 	call	allocate_page
  3674 0000317B 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3675 0000317D 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3676 0000317F 7405                <1> 	jz	short cpp_2
  3677                              <1> 		; Convert read only page to writable page 
  3678                              <1> 		;(for the parent of the current process)
  3679                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3680                              <1> 	; 22/09/2015
  3681 00003181 890E                <1> 	mov	[esi], ecx
  3682 00003183 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3683                              <1> 				 ; 1+2+4 = 7
  3684                              <1> cpp_2:
  3685 00003186 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3686                              <1> 	; 07/09/2015
  3687 00003188 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3688 0000318A B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3689 0000318F F3A5                <1> 	rep	movsd ; 31/08/2015
  3690                              <1> cpp_3:		
  3691 00003191 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3692 00003193 8903                <1> 	mov	[ebx], eax ; Update PTE
  3693 00003195 28C0                <1> 	sub	al, al ; clear attributes
  3694                              <1> cpp_4:
  3695                              <1> 	; 16/04/2021
  3696                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3697                              <1> 	;pop	ecx ; ****
  3698                              <1> 	;pop	ebx ; ***
  3699 00003197 5F                  <1> 	pop	edi ; **
  3700 00003198 5E                  <1> 	pop	esi ; *
  3701 00003199 C3                  <1> 	retn
  3702                              <1> 
  3703                              <1> ;; 28/04/2015
  3704                              <1> ;; 24/10/2014
  3705                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3706                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3707                              <1> ;;
  3708                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3709                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3710                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3711                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3712                              <1> ;;
  3713                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3714                              <1> ;;
  3715                              <1> ;; Method:
  3716                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3717                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3718                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3719                              <1> ;;	When a new page is being allocated, swap queue is updated
  3720                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3721                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3722                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3723                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3724                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3725                              <1> ;;	offset value becomes it's previous offset value - 4.
  3726                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3727                              <1> ;;	the queue/list is not shifted.
  3728                              <1> ;;	After the queue/list shift, newly allocated page is added
  3729                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3730                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3731                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3732                              <1> ;;	
  3733                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3734                              <1> ;;	the first non-accessed, writable page in the list, 
  3735                              <1> ;;	from the head to the tail. The list is shifted to left 
  3736                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3737                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3738                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3739                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3740                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3741                              <1> ;;	procedure will be failed)...
  3742                              <1> ;;
  3743                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3744                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3745                              <1> ;;	(PTE) will be added to the tail of the queue after
  3746                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3747                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3748                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3749                              <1> ;;
  3750                              <1> ;;
  3751                              <1> ;;	
  3752                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3753                              <1> ;;
  3754                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3755                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3756                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3757                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3758                              <1> ;;
  3759                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3760                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3761                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3762                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3763                              <1> ;; 		 (entire swap space must be accessed by using
  3764                              <1> ;;		 31 bit offset address) 
  3765                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3766                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3767                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3768                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3769                              <1> ;;
  3770                              <1> ;; 					
  3771                              <1> ;; Method:
  3772                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3773                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3774                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3775                              <1> ;;	Swapping out is performed by using swap page queue.
  3776                              <1> ;;
  3777                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3778                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3779                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3780                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3781                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3782                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3783                              <1> ;;	calculated by adding offset value to the swap partition's 
  3784                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3785                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3786                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3787                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3788                              <1> ;;	is in a partitioned virtual hard disk.) 
  3789                              <1> ;;
  3790                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3791                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3792                              <1> ;;
  3793                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3794                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3795                              <1> ;;
  3796                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3797                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3798                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3799                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3800                              <1> ;;	it means relevant (respective) block is in use, and, 
  3801                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3802                              <1> ;;      swap disk/file block is free.
  3803                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3804                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3805                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3806                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3807                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3808                              <1> ;;	------------------------------------------------------------
  3809                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3810                              <1> ;;	------------------------------------------------------------
  3811                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3812                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3813                              <1> ;;
  3814                              <1> ;;	..............................................................
  3815                              <1> ;;
  3816                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3817                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3818                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3819                              <1> ;;	position with value of 1 on the table is converted to swap
  3820                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3821                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3822                              <1> ;;	number of physical swap disk or virtual swap disk)
  3823                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3824                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3825                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3826                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3827                              <1> ;;	If disk write procedure returns with error or free count of 
  3828                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3829                              <1> ;;	'insufficient memory error' (cf=1). 
  3830                              <1> ;;
  3831                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3832                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3833                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3834                              <1> ;;	free blocks after a disk write error. It will return to 
  3835                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3836                              <1> ;;
  3837                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3838                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3839                              <1> ;;	address (cf=0). 
  3840                              <1> ;;
  3841                              <1> ;;	..............................................................
  3842                              <1> ;;
  3843                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3844                              <1> ;;	file sectors at specified memory page. Then page allocation
  3845                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3846                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3847                              <1> ;;	to do, except to terminate the process which is the owner of
  3848                              <1> ;;	the swapped page.
  3849                              <1> ;;
  3850                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3851                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3852                              <1> ;;	updates [swpd_first] pointer if it is required.
  3853                              <1> ;;
  3854                              <1> ;;	..............................................................	 
  3855                              <1> ;;
  3856                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3857                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3858                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3859                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3860                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3861                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3862                              <1> ;;
  3863                              <1> 
  3864                              <1> ; 24/12/2021
  3865                              <1> ; ('swap_in' procedure call is disabled)
  3866                              <1> 
  3867                              <1> ;swap_in:
  3868                              <1> 	; 31/08/2015
  3869                              <1> 	; 20/07/2015
  3870                              <1> 	; 28/04/2015
  3871                              <1> 	; 18/04/2015
  3872                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3873                              <1> 	;
  3874                              <1> 	; INPUT -> 
  3875                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3876                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3877                              <1> 	;	EAX = Offset Address for the swapped page on the
  3878                              <1> 	;	      swap disk or in the swap file.
  3879                              <1> 	;
  3880                              <1> 	; OUTPUT ->
  3881                              <1> 	;	EAX = 0 if loading at memory has been successful
  3882                              <1> 	;
  3883                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3884                              <1> 	;		  or sector not present or drive not ready
  3885                              <1> 	;	     EAX = Error code
  3886                              <1> 	;	     [u.error] = EAX 
  3887                              <1> 	;		       = The last error code for the process
  3888                              <1> 	;		         (will be reset after returning to user)	  
  3889                              <1> 	;
  3890                              <1> 	; Modified Registers -> EAX
  3891                              <1> 	;
  3892                              <1> 
  3893                              <1> ;       cmp     dword [swp_drv], 0
  3894                              <1> ;	jna	short swpin_dnp_err
  3895                              <1> ;
  3896                              <1> ;	cmp	eax, [swpd_size]
  3897                              <1> ;	jnb	short swpin_snp_err
  3898                              <1> ;
  3899                              <1> ;	push	esi
  3900                              <1> ;	push	ebx
  3901                              <1> ;	push	ecx
  3902                              <1> ;	mov	esi, [swp_drv]	
  3903                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3904                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3905                              <1> ;		; size different than 512 bytes, logical disk sector
  3906                              <1> ;		; size is 512 bytes and disk reading procedure
  3907                              <1> ;		; will be performed for reading 4096 bytes
  3908                              <1> ;		; (2*2048, 8*512). 
  3909                              <1> ;	; ESI = Logical disk description table address
  3910                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3911                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3912                              <1> ;	; ECX = Sector count ; 8 sectors
  3913                              <1> ;	push	eax
  3914                              <1> ;	call	logical_disk_read
  3915                              <1> ;	pop	eax
  3916                              <1> ;	jnc	short swpin_read_ok
  3917                              <1> ;	;
  3918                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3919                              <1> ;	mov	[u.error], eax
  3920                              <1> ;	jmp	short swpin_retn
  3921                              <1> ;	;
  3922                              <1> ;swpin_read_ok:
  3923                              <1> ;	; EAX = Offset address (logical sector number)
  3924                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3925                              <1> ;	;
  3926                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3927                              <1> ;	; 20/07/2015
  3928                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3929                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3930                              <1> ;	mov	bl, [u.uno] ; current process number
  3931                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3932                              <1> ;	call	swap_queue_shift
  3933                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3934                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3935                              <1> ;	; zf = 1
  3936                              <1> ;swpin_retn:
  3937                              <1> ;	pop	ecx
  3938                              <1> ;	pop	ebx
  3939                              <1> ;	pop	esi
  3940                              <1> ;	retn
  3941                              <1> ;
  3942                              <1> ;swpin_dnp_err:
  3943                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3944                              <1> ;swpin_err_retn:
  3945                              <1> ;	mov	[u.error], eax
  3946                              <1> ;	stc
  3947                              <1> ;	retn
  3948                              <1> ;
  3949                              <1> ;swpin_snp_err:
  3950                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3951                              <1> ;	jmp	short swpin_err_retn
  3952                              <1> 
  3953                              <1> ; 24/12/2021
  3954                              <1> ; ('swap_out' procedure call is disabled)
  3955                              <1> 
  3956                              <1> ;swap_out:
  3957                              <1> 	; 10/06/2016
  3958                              <1> 	; 07/06/2016
  3959                              <1>         ; 23/05/2016
  3960                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3961                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3962                              <1> 	;
  3963                              <1> 	; INPUT -> 
  3964                              <1> 	;	none
  3965                              <1> 	;
  3966                              <1> 	; OUTPUT ->
  3967                              <1> 	;	EAX = Physical page address (which is swapped out
  3968                              <1> 	;	      for allocating a new page)
  3969                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3970                              <1> 	;		  or sector not present or drive not ready
  3971                              <1> 	;	     EAX = Error code
  3972                              <1> 	;	     [u.error] = EAX 
  3973                              <1> 	;		       = The last error code for the process
  3974                              <1> 	;		         (will be reset after returning to user)	  
  3975                              <1> 	;
  3976                              <1> 	; Modified Registers -> none (except EAX)
  3977                              <1> 	;
  3978                              <1> 
  3979                              <1> ;	cmp 	word [swpq_count], 1
  3980                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3981                              <1> ;
  3982                              <1> ;       ;cmp    dword [swp_drv], 1
  3983                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3984                              <1> ;
  3985                              <1> ;       cmp     dword [swpd_free], 1
  3986                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3987                              <1> ;
  3988                              <1> ;	push	ebx ; *
  3989                              <1> ;swpout_1:
  3990                              <1> ;	; 10/06/2016
  3991                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3992                              <1> ;	call	swap_queue_shift
  3993                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3994                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3995                              <1> ;				       ; pointer in the swap queue
  3996                              <1> ;	; EAX = PTE value of the page
  3997                              <1> ;	; EBX = PTE address of the page
  3998                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3999                              <1> ;	;
  4000                              <1> ;	; 07/06/2016
  4001                              <1> ;	; 19/05/2016
  4002                              <1> ;	; check this page is in timer events or not
  4003                              <1> ;	
  4004                              <1> ;swpout_timer_page_0:
  4005                              <1> ;	push	edx ; **
  4006                              <1> ;
  4007                              <1> ;	; 07/06/2016
  4008                              <1> ;	cmp	byte [timer_events], 0 
  4009                              <1> ;	jna	short swpout_2
  4010                              <1> ;	;
  4011                              <1> ;	mov	dl, [timer_events]
  4012                              <1> ;
  4013                              <1> ;	push	ecx ; ***
  4014                              <1> ;	push	ebx ; ****
  4015                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4016                              <1> ;			       ; structures 
  4017                              <1> ;swpout_timer_page_1:
  4018                              <1> ;	mov	cl, [ebx]
  4019                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4020                              <1> ;	jz	short swpout_timer_page_3
  4021                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4022                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4023                              <1> ;				; of the response byte address, to
  4024                              <1> ;				; get beginning of the page address)
  4025                              <1> ;	cmp	eax, ecx
  4026                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4027                              <1> ;	
  4028                              <1> ;	; !same page!
  4029                              <1> ;	;
  4030                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4031                              <1> ;	; This page will be used by the kernel to put timer event
  4032                              <1> ;	; response (signal return) byte at the requested address;
  4033                              <1> ;	; in order to prevent a possible wrong write (while
  4034                              <1> ;	; this page is swapped out) on physical memory,
  4035                              <1> ;	; we must protect this page against to be swapped out!
  4036                              <1> ;	;
  4037                              <1> ;	pop	ebx ; ****
  4038                              <1> ;	pop	ecx ; ***
  4039                              <1> ;	pop	edx ; **
  4040                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4041                              <1> ; 
  4042                              <1> ;swpout_timer_page_2:
  4043                              <1> ;	; 07/06/2016
  4044                              <1> ;	dec	dl
  4045                              <1> ;	jz	short swpout_timer_page_4
  4046                              <1> ;swpout_timer_page_3:
  4047                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4048                              <1> ;	;jnb	short swpout_timer_page_4
  4049                              <1> ;	add	ebx, 16
  4050                              <1> ;	jmp	short swpout_timer_page_1	
  4051                              <1> ;
  4052                              <1> ;swpout_timer_page_4:
  4053                              <1> ;	pop	ebx ; ****
  4054                              <1> ;	pop	ecx ; ***
  4055                              <1> ;swpout_2:
  4056                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4057                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4058                              <1> ;	;
  4059                              <1> ;	call	link_swap_block
  4060                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4061                              <1> ;				       ; because [swpd_free] value
  4062                              <1> ;				       ; was checked at the beginging. 	
  4063                              <1> ;	pop	edx ; **
  4064                              <1> ;	pop	ebx ; *
  4065                              <1> ;	jmp	short swpout_nfspc_err 
  4066                              <1> ;swpout_3:
  4067                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4068                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4069                              <1> ;	;	
  4070                              <1> ;	push	esi ; **
  4071                              <1> ;	push	ecx ; ***
  4072                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4073                              <1> ;	mov	esi, [swp_drv]	
  4074                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4075                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4076                              <1> ;		; size different than 512 bytes, logical disk sector
  4077                              <1> ;		; size is 512 bytes and disk writing procedure
  4078                              <1> ;		; will be performed for writing 4096 bytes
  4079                              <1> ;		; (2*2048, 8*512). 
  4080                              <1> ;	; ESI = Logical disk description table address
  4081                              <1> ;	; EBX = Buffer (Page) address
  4082                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4083                              <1> ;	; ECX = Sector count ; 8 sectors
  4084                              <1> ;	; edx = PTE address
  4085                              <1> ;	call	logical_disk_write
  4086                              <1> ;	; edx = PTE address
  4087                              <1> ;	pop	ecx ; sector address	
  4088                              <1> ;	jnc	short swpout_write_ok
  4089                              <1> ;	;
  4090                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4091                              <1> ;swpout_dw_err:
  4092                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4093                              <1> ;	mov	[u.error], eax
  4094                              <1> ;	jmp	short swpout_retn
  4095                              <1> ;	;
  4096                              <1> ;swpout_write_ok:
  4097                              <1> ;	; EBX = Buffer (page) address
  4098                              <1> ;	; EDX = Page Table Entry address
  4099                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4100                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4101                              <1> ;	mov 	[edx], ecx 
  4102                              <1> ;		; bit 0 = 0 (swapped page)
  4103                              <1> ;	mov	eax, ebx
  4104                              <1> ;swpout_retn:
  4105                              <1> ;	pop	ecx ; ***
  4106                              <1> ;	pop	esi ; **
  4107                              <1> ;	pop	ebx ; *
  4108                              <1> ;	retn
  4109                              <1> ;
  4110                              <1> ;;swpout_dnp_err:
  4111                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4112                              <1> ;;	jmp	short swpout_err_retn
  4113                              <1> ;swpout_nfspc_err:
  4114                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4115                              <1> ;swpout_err_retn:
  4116                              <1> ;	mov	[u.error], eax
  4117                              <1> ;	;stc
  4118                              <1> ;	retn
  4119                              <1> ;swpout_npts_err:
  4120                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4121                              <1> ;	pop	ebx
  4122                              <1> ;	jmp	short swpout_err_retn
  4123                              <1> ;swpout_im_err:
  4124                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4125                              <1> ;	jmp	short swpout_err_retn
  4126                              <1> 
  4127                              <1> ; 24/12/2021
  4128                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4129                              <1> 
  4130                              <1> ;swap_queue_shift:
  4131                              <1> 	; 26/03/2017
  4132                              <1> 	; 10/06/2016
  4133                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4134                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4135                              <1> 	;
  4136                              <1> 	; INPUT ->
  4137                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4138                              <1> 	;	      and process number combination (bit 0 to 11)
  4139                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4140                              <1> 	;	
  4141                              <1> 	; OUTPUT ->
  4142                              <1> 	;	If EBX input > 0 
  4143                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4144                              <1> 	; 	   from the tail to the head, up to entry offset
  4145                              <1> 	; 	   which points to EBX input value or nothing
  4146                              <1> 	;	   to do if EBX value is not found on the queue.
  4147                              <1> 	;	   (The entry -with EBX value- will be removed
  4148                              <1> 	;	   from the queue if it is found.)
  4149                              <1> 	;
  4150                              <1> 	;	   EAX = 0		
  4151                              <1> 	;
  4152                              <1> 	;	If EBX input = 0
  4153                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4154                              <1> 	; 	   from the tail to the head, if the PTE address
  4155                              <1> 	;	   which is pointed in head of the queue is marked
  4156                              <1> 	;	   as "accessed" or it is marked as "non present".
  4157                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4158                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4159                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4160                              <1> 	;	   -without dropping pointer of the PTE from 
  4161                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4162                              <1> 	;	   Pointer in the head will be moved into the tail,
  4163                              <1> 	;	   other PTEs will be shifted on head direction.)
  4164                              <1> 	;
  4165                              <1> 	;	   Swap queue will be shifted up to the first
  4166                              <1> 	;	   'present' or 'non accessed' page will be found
  4167                              <1> 	;	   (as pointed) on the queue head (then it will be
  4168                              <1>         ;          removed/dropped from the queue).
  4169                              <1> 	;
  4170                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4171                              <1> 	;		 (it's pointer -virtual address-) dropped
  4172                              <1> 	;		 (removed) from swap queue.
  4173                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4174                              <1> 	;	         which is (it's pointer -virtual address-)
  4175                              <1> 	;		 dropped (removed) from swap queue.
  4176                              <1> 	;
  4177                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4178                              <1> 	;
  4179                              <1> 	; Modified Registers -> EAX, EBX
  4180                              <1> 	;
  4181                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4182                              <1> ;	and	ax, ax
  4183                              <1> ;	jz	short swpqs_retn
  4184                              <1> ;	push	edi
  4185                              <1> ;	push	esi
  4186                              <1> ;	push	ecx
  4187                              <1> ;	mov	esi, swap_queue
  4188                              <1> ;	mov	ecx, eax
  4189                              <1> ;	or	ebx, ebx
  4190                              <1> ;	jz	short swpqs_7
  4191                              <1> ;swpqs_1:
  4192                              <1> ;	lodsd
  4193                              <1> ;	cmp	eax, ebx
  4194                              <1> ;	je	short swpqs_2
  4195                              <1> ;	loop	swpqs_1
  4196                              <1> ;	; 10/06/2016
  4197                              <1> ;	sub	eax, eax 
  4198                              <1> ;	jmp	short swpqs_6
  4199                              <1> ;swpqs_2:
  4200                              <1> ;	mov	edi, esi
  4201                              <1> ;	sub 	edi, 4
  4202                              <1> ;swpqs_3:
  4203                              <1> ;	dec	word [swpq_count]
  4204                              <1> ;	jz	short swpqs_5
  4205                              <1> ;swpqs_4:
  4206                              <1> ;	dec 	ecx
  4207                              <1> ;	rep	movsd	; shift up (to the head)
  4208                              <1> ;swpqs_5:
  4209                              <1> ;	xor	eax, eax
  4210                              <1> ;	mov	[edi], eax
  4211                              <1> ;swpqs_6:
  4212                              <1> ;	pop	ecx
  4213                              <1> ;	pop	esi
  4214                              <1> ;	pop	edi
  4215                              <1> ;swpqs_retn:
  4216                              <1> ;	retn		
  4217                              <1> ;swpqs_7:
  4218                              <1> ;	mov	edi, esi ; head
  4219                              <1> ;	lodsd
  4220                              <1> ;	; 20/07/2015
  4221                              <1> ;	mov	ebx, eax
  4222                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4223                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4224                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4225                              <1> ;		      ; ax = process number (1 to 4095)
  4226                              <1> ;	cmp	al, [u.uno]
  4227                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4228                              <1> ;	jne	short swpqs_8
  4229                              <1> ;	mov	eax, [u.pgdir]
  4230                              <1> ;	jmp	short swpqs_9
  4231                              <1> ;swpqs_8:
  4232                              <1> ;	; 09/06/2016
  4233                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4234                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4235                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4236                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4237                              <1> ;
  4238                              <1> ;	;shl	ax, 2
  4239                              <1> ;	shl	al, 2
  4240                              <1> ;	mov 	eax, [eax+p.upage-4]
  4241                              <1> ;	or	eax, eax
  4242                              <1> ;	jz	short swpqs_3 ; invalid upage
  4243                              <1> ;	add	eax, u.pgdir - user
  4244                              <1> ;			 ; u.pgdir value for the process
  4245                              <1> ;			 ; is in [eax]
  4246                              <1> ;	mov	eax, [eax]
  4247                              <1> ;	and	eax, eax
  4248                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4249                              <1> ;swpqs_9:
  4250                              <1> ;	push	edx
  4251                              <1> ;	; eax = page directory
  4252                              <1> ;	; ebx = virtual address
  4253                              <1> ;	call	get_pte
  4254                              <1> ;	mov	ebx, edx	; PTE address
  4255                              <1> ;	pop	edx
  4256                              <1> ;	; 10/06/2016
  4257                              <1> ;	jc	short swpqs_13 ; empty PDE
  4258                              <1> ;	; EAX = PTE value
  4259                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4260                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4261                              <1> ;			        ; from the queue (head)
  4262                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4263                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4264                              <1> ;			        ; from the queue (head) 	
  4265                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4266                              <1> ;	;jnz	short swpqs_11  ; present
  4267                              <1> ;			        ; accessed page
  4268                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4269                              <1> ;	jc	short swpqs_11  ; accessed page
  4270                              <1> ;
  4271                              <1> ;	dec	ecx
  4272                              <1> ;	mov	[swpq_count], cx
  4273                              <1> ;       jz      short swpqs_10
  4274                              <1> ;		; esi = head + 4
  4275                              <1> ;		; edi = head
  4276                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4277                              <1> ;swpqs_10:
  4278                              <1> ;	mov	[edi], ecx ; 0
  4279                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4280                              <1> ;
  4281                              <1> ;swpqs_11:
  4282                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4283                              <1> ;	; Rotation (head -> tail)
  4284                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4285                              <1> ;	jz	short swpqs_10
  4286                              <1> ;		; esi = head + 4
  4287                              <1> ;		; edi = head
  4288                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4289                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4290                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4291                              <1> ;
  4292                              <1> ;	mov	cx, [swpq_count]
  4293                              <1> ;
  4294                              <1> ;swpqs_12:
  4295                              <1> ;	mov	esi, swap_queue ; head
  4296                              <1> ;       jmp     swpqs_7
  4297                              <1> ;
  4298                              <1> ;swpqs_13:
  4299                              <1> ;	dec	ecx
  4300                              <1> ;	mov	[swpq_count], cx
  4301                              <1> ;       jz      swpqs_5
  4302                              <1> ;	jmp	short swpqs_12
  4303                              <1> 
  4304                              <1> ; 24/12/2021
  4305                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4306                              <1> 
  4307                              <1> ;add_to_swap_queue:
  4308                              <1> 	; 20/02/2017
  4309                              <1> 	; 20/07/2015
  4310                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4311                              <1> 	;
  4312                              <1> 	; Adds new page to swap queue
  4313                              <1> 	; (page directories and page tables must not be added
  4314                              <1> 	; to swap queue)	
  4315                              <1> 	;
  4316                              <1> 	; INPUT ->
  4317                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4318                              <1> 	;	[u.uno]
  4319                              <1> 	;	20/02/2017
  4320                              <1> 	;	(Linear address = CORE + user's virtual address)
  4321                              <1> 	;
  4322                              <1> 	; OUTPUT ->
  4323                              <1> 	;	EAX = [swpq_count]
  4324                              <1> 	;	      (after the PTE has been added)
  4325                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4326                              <1> 	;	      the PTE could not be added.
  4327                              <1> 	;
  4328                              <1> 	; Modified Registers -> EAX
  4329                              <1> 	;
  4330                              <1> ;	push	ebx
  4331                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4332                              <1> ;	mov	bl, [u.uno] ; current process number
  4333                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4334                              <1> ;				 ; it is already on the queue
  4335                              <1> ;		; then add it to the tail of the queue
  4336                              <1> ;	movzx	eax, word [swpq_count]
  4337                              <1> ;	cmp	ax, 1024
  4338                              <1> ;	jb	short atsq_1
  4339                              <1> ;	sub	ax, ax
  4340                              <1> ;	pop	ebx
  4341                              <1> ;	retn
  4342                              <1> ;atsq_1:
  4343                              <1> ;	push	esi
  4344                              <1> ;	mov	esi, swap_queue
  4345                              <1> ;	and	ax, ax
  4346                              <1> ;	jz	short atsq_2
  4347                              <1> ;	shl	ax, 2	; convert to offset
  4348                              <1> ;	add	esi, eax
  4349                              <1> ;	shr	ax, 2
  4350                              <1> ;atsq_2:
  4351                              <1> ;	inc	ax
  4352                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4353                              <1> ;	mov	[swpq_count], ax
  4354                              <1> ;	pop	esi
  4355                              <1> ;	pop	ebx
  4356                              <1> ;	retn
  4357                              <1> 
  4358                              <1> ; 24/12/2021
  4359                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4360                              <1> 
  4361                              <1> ;unlink_swap_block:
  4362                              <1> 	; 15/09/2015
  4363                              <1> 	; 30/04/2015
  4364                              <1> 	; 18/04/2015
  4365                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4366                              <1> 	;
  4367                              <1> 	; INPUT -> 
  4368                              <1> 	;	EAX = swap disk/file offset address
  4369                              <1> 	;	      (bit 1 to bit 31)
  4370                              <1> 	; OUTPUT ->
  4371                              <1> 	;	[swpd_free] is increased
  4372                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4373                              <1> 	;
  4374                              <1> 	; Modified Registers -> EAX
  4375                              <1> 	;
  4376                              <1> ;	push	ebx
  4377                              <1> ;	push	edx
  4378                              <1> ;	;
  4379                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4380                              <1> ;				     ; 3 bits right
  4381                              <1> ;				     ; to get swap block/page number
  4382                              <1> ;	mov	edx, eax
  4383                              <1> ;	; 15/09/2015
  4384                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4385                              <1> ;				     ; (1 allocation bit = 1 page)
  4386                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4387                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4388                              <1> ;				     ; (to get 32 bit position)			
  4389                              <1> ;	;
  4390                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4391                              <1> ;	add	ebx, edx
  4392                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4393                              <1> ;				     ; (allocation bit position)	 
  4394                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4395                              <1> ;				     ; than the address in 'swpd_next' ?
  4396                              <1> ;				     ; (next/first free block value)		
  4397                              <1> ;	jnb	short uswpbl_1	     ; no	
  4398                              <1> ;	mov	[swpd_next], eax     ; yes	
  4399                              <1> ;uswpbl_1:
  4400                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4401                              <1> ;				     ; set relevant bit to 1.
  4402                              <1> ;				     ; set CF to the previous bit value	
  4403                              <1> ;	cmc			     ; complement carry flag	
  4404                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4405                              <1> ;				     ; if the block is already deallocated
  4406                              <1> ;				     ; before.	
  4407                              <1> ;       inc     dword [swpd_free]
  4408                              <1> ;uswpbl_2:
  4409                              <1> ;	pop	edx
  4410                              <1> ;	pop	ebx
  4411                              <1> ;	retn
  4412                              <1> 
  4413                              <1> ; 24/12/2021
  4414                              <1> ; ('link_swap_block' procedure call is disabled)
  4415                              <1> 
  4416                              <1> ;link_swap_block:
  4417                              <1> 	; 01/07/2015
  4418                              <1> 	; 18/04/2015
  4419                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4420                              <1> 	;
  4421                              <1> 	; INPUT -> none
  4422                              <1> 	;
  4423                              <1> 	; OUTPUT ->
  4424                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4425                              <1> 	;	      in sectors (corresponding 
  4426                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4427                              <1> 	;
  4428                              <1> 	;	CF = 1 and EAX = 0 
  4429                              <1> 	; 		   if there is not a free block to be allocated	
  4430                              <1> 	;
  4431                              <1> 	; Modified Registers -> none (except EAX)
  4432                              <1> 	;
  4433                              <1> 
  4434                              <1> ;	;mov	eax, [swpd_free]
  4435                              <1> ;	;and	eax, eax
  4436                              <1> ;	;jz	short out_of_swpspc
  4437                              <1> ;	;
  4438                              <1> ;	push	ebx
  4439                              <1> ;	push	ecx
  4440                              <1> ;	;
  4441                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4442                              <1> ;	mov	ecx, ebx
  4443                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4444                              <1> ;				 ; next_free_swap_block >> 5
  4445                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4446                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4447                              <1> ;lswbl_scan:
  4448                              <1> ;	cmp	ebx, ecx
  4449                              <1> ;	ja	short lswbl_notfound
  4450                              <1> ;	;
  4451                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4452                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4453                              <1> ;			   ; loads the destination with an index to
  4454                              <1> ;			   ; first set bit. (0 -> 31) 
  4455                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4456                              <1> ;	; 01/07/2015
  4457                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4458                              <1> ;			 ;
  4459                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4460                              <1> ;			 ;	  with value of 1 means 
  4461                              <1> ;			 ;	  the corresponding page is free 
  4462                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4463                              <1> ;	add	ebx, 4
  4464                              <1> ;			 ; We return back for searching next page block
  4465                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4466                              <1> ;			 ;	 we always will find at least 1 free block here.
  4467                              <1> ;	jmp    	short lswbl_scan
  4468                              <1> ;	;
  4469                              <1> ;lswbl_notfound:	
  4470                              <1> ;	sub	ecx, swap_alloc_table
  4471                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4472                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4473                              <1> ;	xor	eax, eax
  4474                              <1> ;	mov	[swpd_free], eax
  4475                              <1> ;	stc
  4476                              <1> ;lswbl_ok:
  4477                              <1> ;	pop	ecx
  4478                              <1> ;	pop	ebx
  4479                              <1> ;	retn
  4480                              <1> ;	;
  4481                              <1> ;;out_of_swpspc:
  4482                              <1> ;;	stc
  4483                              <1> ;;	retn
  4484                              <1> ;
  4485                              <1> ;lswbl_found:
  4486                              <1> ;	mov	ecx, ebx
  4487                              <1> ;	sub	ecx, swap_alloc_table
  4488                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4489                              <1> ;				 ; address/offset (to the next)
  4490                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4491                              <1> ;	;
  4492                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4493                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4494                              <1> ;				 ; in the destination.
  4495                              <1> ;				 ;
  4496                              <1> ;				 ; Reset the bit which is corresponding to the 
  4497                              <1> ;				 ; (just) allocated block.
  4498                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4499                              <1> ;	add	eax, ecx	 ; = block number
  4500                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4501                              <1> ;				 ; 1 block =  8 sectors
  4502                              <1> ;	;
  4503                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4504                              <1> ;	;
  4505                              <1> ;	; NOTE: The relevant page table entry will be updated
  4506                              <1> ;	;       according to this EAX value...
  4507                              <1> ;	;
  4508                              <1> ;	jmp	short lswbl_ok
  4509                              <1> 
  4510                              <1> ; 24/12/2021
  4511                              <1> ; ('logical_disk_read' procedure call is disabled)
  4512                              <1> 
  4513                              <1> ;logical_disk_read:
  4514                              <1> 	; 20/07/2015
  4515                              <1> 	; 09/03/2015 (temporary code here)
  4516                              <1> 	;
  4517                              <1> 	; INPUT ->
  4518                              <1> 	; 	ESI = Logical disk description table address
  4519                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4520                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4521                              <1> 	; 	ECX = Sector count
  4522                              <1> 	;
  4523                              <1> 	;
  4524                              <1> ;	retn
  4525                              <1> 
  4526                              <1> ; 24/12/2021
  4527                              <1> ; ('logical_disk_write' procedure call is disabled)
  4528                              <1> 
  4529                              <1> ;logical_disk_write:
  4530                              <1> 	; 20/07/2015
  4531                              <1> 	; 09/03/2015 (temporary code here)
  4532                              <1> 	;
  4533                              <1> 	; INPUT ->
  4534                              <1> 	; 	ESI = Logical disk description table address
  4535                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4536                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4537                              <1> 	; 	ECX = Sector count
  4538                              <1> 	;
  4539                              <1> ;	retn
  4540                              <1> 
  4541                              <1> get_physical_addr:
  4542                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4543                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4544                              <1> 	; 18/10/2015
  4545                              <1> 	; 29/07/2015
  4546                              <1> 	; 20/07/2015
  4547                              <1> 	; 04/06/2015
  4548                              <1> 	; 20/05/2015
  4549                              <1> 	; 28/04/2015
  4550                              <1> 	; 18/04/2015
  4551                              <1> 	; Get physical address
  4552                              <1> 	;     (allocates a new page for user if it is not present)
  4553                              <1> 	;	
  4554                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4555                              <1> 	; (buffer) address to physical address (of the buffer).)
  4556                              <1> 	; ('sys write', 'sys read' system calls...)
  4557                              <1> 	;
  4558                              <1> 	; INPUT ->
  4559                              <1> 	;	EBX = virtual address
  4560                              <1> 	;	u.pgdir = page directory (physical) address
  4561                              <1> 	;
  4562                              <1> 	; OUTPUT ->
  4563                              <1> 	;	EAX = physical address 
  4564                              <1> 	;	EBX = linear address	
  4565                              <1> 	;	EDX = physical address of the page frame
  4566                              <1> 	;	      (with attribute bits)
  4567                              <1> 	;	ECX = byte count within the page frame
  4568                              <1> 	;
  4569                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4570                              <1> 	;
  4571                              <1> 
  4572                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4573 0000319A A1[A5700000]        <1> 	mov	eax, [u.pgdir]
  4574                              <1> 
  4575                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4576                              <1> 	
  4577 0000319F 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4578                              <1> 	;
  4579                              <1> 	;mov	eax, [u.pgdir]
  4580 000031A5 E816FDFFFF          <1> 	call	get_pte
  4581                              <1> 		; EDX = Page table entry address (if CF=0)
  4582                              <1> 	        ;       Page directory entry address (if CF=1)
  4583                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4584                              <1> 		; EAX = Page table entry value (page address)
  4585                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4586 000031AA 731C                <1> 	jnc	short gpa_1
  4587                              <1> 	;
  4588 000031AC E8FDFBFFFF          <1> 	call	allocate_page
  4589 000031B1 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4590                              <1> gpa_0:
  4591 000031B3 E867FCFFFF          <1> 	call 	clear_page
  4592                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4593 000031B8 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4594                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4595                              <1> 			   ; (user, writable, present page)	
  4596 000031BA 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4597 000031BC A1[A5700000]        <1> 	mov	eax, [u.pgdir]	
  4598 000031C1 E8FAFCFFFF          <1> 	call	get_pte
  4599 000031C6 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4600                              <1> gpa_1:
  4601                              <1> 	; EAX = PTE value, EDX = PTE address
  4602 000031C8 A801                <1> 	test 	al, PTE_A_PRESENT
  4603 000031CA 750A                <1> 	jnz	short gpa_3
  4604 000031CC 09C0                <1> 	or	eax, eax
  4605 000031CE 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4606                              <1> 
  4607                              <1> ; 24/12/2021
  4608                              <1> ; ('reload_page' procedure call is disabled)
  4609 000031D0 EB2C                <1> 	jmp	short gpa_im_err
  4610                              <1> 
  4611                              <1> 	; 20/07/2015
  4612                              <1> ;	push	ebp
  4613                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4614                              <1> ;	; reload swapped page
  4615                              <1> ;	call	reload_page ; 28/04/2015
  4616                              <1> ;	pop	ebp
  4617                              <1> ;	jc	short gpa_retn
  4618                              <1> gpa_2:
  4619                              <1> ; 24/12/2021
  4620                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4621                              <1> 
  4622                              <1> 	; 20/07/2015
  4623                              <1> 	; 20/05/2015
  4624                              <1> 	; add this page to swap queue
  4625                              <1> ;	push	eax 
  4626                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4627                              <1> ;	call 	add_to_swap_queue
  4628                              <1> ;	pop	eax
  4629                              <1> 		; PTE address in EDX
  4630                              <1> 		; virtual address in EBX
  4631                              <1> 	; EAX = memory page address
  4632 000031D2 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4633                              <1> 				  ; present flag, bit 0 = 1
  4634                              <1> 				  ; user flag, bit 2 = 1	
  4635                              <1> 				  ; writable flag, bit 1 = 1
  4636 000031D4 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4637                              <1> gpa_3:
  4638                              <1> 	; 18/10/2015
  4639 000031D6 89D9                <1> 	mov	ecx, ebx
  4640 000031D8 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4641 000031DE 89C2                <1> 	mov 	edx, eax
  4642 000031E0 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4643 000031E4 01C8                <1> 	add	eax, ecx
  4644 000031E6 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4645 000031E8 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4646 000031EE F8                  <1> 	clc
  4647                              <1> gpa_retn:
  4648 000031EF C3                  <1> 	retn	
  4649                              <1> gpa_4:	
  4650 000031F0 E8B9FBFFFF          <1> 	call	allocate_page
  4651 000031F5 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4652 000031F7 E823FCFFFF          <1> 	call	clear_page
  4653 000031FC EBD4                <1> 	jmp	short gpa_2
  4654                              <1> 
  4655                              <1> gpa_im_err:	
  4656 000031FE B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4657                              <1> 				  ; Major error = 0 (No protection fault)	
  4658 00003203 C3                  <1> 	retn
  4659                              <1> 
  4660                              <1> ; 24/12/2021
  4661                              <1> ; ('reload_page' procedure call is disabled)
  4662                              <1> 
  4663                              <1> ;reload_page:
  4664                              <1> 	; 20/07/2015
  4665                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4666                              <1> 	;
  4667                              <1> 	; Reload (Restore) swapped page at memory
  4668                              <1> 	;
  4669                              <1> 	; INPUT -> 
  4670                              <1> 	;	EBP = Virtual (linear) memory address
  4671                              <1> 	;	EAX = PTE value (swap disk sector address)
  4672                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4673                              <1> 	; OUTPUT ->
  4674                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4675                              <1> 	;
  4676                              <1> 	;	CF = 1 and EAX = error code
  4677                              <1> 	;
  4678                              <1> 	; Modified Registers -> none (except EAX)
  4679                              <1> 	;
  4680                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4681                              <1> ;	push	ebx      ;
  4682                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4683                              <1> ;	call	allocate_page
  4684                              <1> ;	jc	short rlp_im_err
  4685                              <1> ;	xchg 	eax, ebx	
  4686                              <1> ;	; EBX = Physical memory (page) address
  4687                              <1> ;	; EAX = Swap disk (offset) address
  4688                              <1> ;	; EBP = Virtual (linear) memory address
  4689                              <1> ;	call	swap_in
  4690                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4691                              <1> ;	mov	eax, ebx	
  4692                              <1> ;rlp_retn:
  4693                              <1> ;	pop	ebx
  4694                              <1> ;	retn
  4695                              <1> ;	
  4696                              <1> ;rlp_im_err:	
  4697                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4698                              <1> ;				  ; Major error = 0 (No protection fault)	
  4699                              <1> ;	jmp	short rlp_retn
  4700                              <1> ;
  4701                              <1> ;rlp_swp_err:
  4702                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4703                              <1> ;	jmp	short rlp_retn
  4704                              <1> 
  4705                              <1> copy_page_dir:
  4706                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4707                              <1> 	; 19/09/2015
  4708                              <1> 	; temporary - 07/09/2015
  4709                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4710                              <1> 	;
  4711                              <1> 	; INPUT -> 
  4712                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4713                              <1> 	;		    page directory.
  4714                              <1> 	; OUTPUT ->
  4715                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4716                              <1> 	;	       page directory.
  4717                              <1> 	;	(New page directory with new page table entries.)
  4718                              <1> 	;	(New page tables with read only copies of the parent's
  4719                              <1> 	;	pages.)
  4720                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4721                              <1> 	;
  4722                              <1> 	; Modified Registers -> none (except EAX)
  4723                              <1> 	;
  4724 00003204 E8A5FBFFFF          <1> 	call	allocate_page
  4725 00003209 723E                <1> 	jc	short cpd_err
  4726                              <1> 	;
  4727 0000320B 55                  <1> 	push	ebp ; 20/07/2015
  4728 0000320C 56                  <1> 	push	esi
  4729 0000320D 57                  <1> 	push	edi
  4730 0000320E 53                  <1> 	push	ebx
  4731 0000320F 51                  <1> 	push	ecx
  4732 00003210 8B35[A5700000]      <1> 	mov	esi, [u.pgdir]
  4733 00003216 89C7                <1> 	mov	edi, eax
  4734 00003218 50                  <1> 	push	eax ; save child's page directory address
  4735                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4736                              <1> 	; (use same system space for all user page tables) 
  4737 00003219 A5                  <1> 	movsd
  4738 0000321A BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4739 0000321F B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4740                              <1> cpd_0:	
  4741 00003224 AD                  <1> 	lodsd
  4742                              <1> 	;or	eax, eax
  4743                              <1>         ;jnz	short cpd_1
  4744 00003225 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4745 00003227 7508                <1> 	jnz	short cpd_1
  4746                              <1>  	; (virtual address at the end of the page table)	
  4747 00003229 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4748 0000322F EB0F                <1> 	jmp	short cpd_2
  4749                              <1> cpd_1:	
  4750 00003231 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4751 00003235 89C3                <1> 	mov	ebx, eax
  4752                              <1> 	; EBX = Parent's page table address
  4753 00003237 E81F000000          <1> 	call	copy_page_table
  4754 0000323C 720C                <1> 	jc	short cpd_p_err
  4755                              <1> 	; EAX = Child's page table address
  4756 0000323E 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4757                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4758                              <1> 			 ; (present, writable, user)
  4759                              <1> cpd_2:
  4760 00003240 AB                  <1> 	stosd
  4761 00003241 E2E1                <1> 	loop	cpd_0
  4762                              <1> 	;
  4763 00003243 58                  <1> 	pop	eax  ; restore child's page directory address
  4764                              <1> cpd_3:
  4765 00003244 59                  <1> 	pop	ecx
  4766 00003245 5B                  <1> 	pop	ebx
  4767 00003246 5F                  <1> 	pop	edi
  4768 00003247 5E                  <1> 	pop	esi
  4769 00003248 5D                  <1> 	pop	ebp
  4770                              <1> cpd_err:
  4771 00003249 C3                  <1> 	retn
  4772                              <1> cpd_p_err:
  4773                              <1> 	; release the allocated pages missing (recover free space)
  4774 0000324A 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4775 0000324B 8B1D[A5700000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4776 00003251 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4777 00003256 29C0                <1> 	sub	eax, eax ; 0
  4778 00003258 F9                  <1> 	stc
  4779 00003259 EBE9                <1> 	jmp	short cpd_3	
  4780                              <1> 
  4781                              <1> copy_page_table:
  4782                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4783                              <1> 	; 19/09/2015
  4784                              <1> 	; temporary - 07/09/2015
  4785                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4786                              <1> 	;
  4787                              <1> 	; INPUT -> 
  4788                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4789                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4790                              <1> 	; OUTPUT ->
  4791                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4792                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4793                              <1> 	;	CF = 1 -> error 
  4794                              <1> 	;
  4795                              <1> 	; Modified Registers -> EBP (except EAX)
  4796                              <1> 	;
  4797 0000325B E84EFBFFFF          <1> 	call	allocate_page
  4798 00003260 7244                <1> 	jc	short cpt_err
  4799                              <1> 	;
  4800 00003262 50                  <1> 	push	eax ; *
  4801                              <1> 	;push 	ebx
  4802 00003263 56                  <1> 	push	esi
  4803 00003264 57                  <1> 	push	edi
  4804 00003265 52                  <1> 	push	edx
  4805 00003266 51                  <1> 	push	ecx
  4806                              <1> 	;
  4807 00003267 89DE                <1> 	mov	esi, ebx
  4808 00003269 89C7                <1> 	mov	edi, eax
  4809 0000326B 89C2                <1> 	mov	edx, eax
  4810 0000326D 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4811                              <1> cpt_0:
  4812 00003273 AD                  <1> 	lodsd
  4813 00003274 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4814                              <1> 	;jnz	short cpt_1 (*)
  4815                              <1> 	; 24/12/2021
  4816                              <1> 	;and	eax, eax (*)
  4817 00003276 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4818                              <1> 	
  4819                              <1> ; 24/12/2021
  4820                              <1> ; ('reload_page' procedure call is disabled)
  4821                              <1> ;
  4822                              <1> ;	; ebp = virtual (linear) address of the memory page
  4823                              <1> ;	call	reload_page ; 28/04/2015
  4824                              <1> ;	jc	short cpt_p_err
  4825                              <1> cpt_1:
  4826 00003278 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4827 0000327C 89C1                <1> 	mov	ecx, eax
  4828                              <1> 	; Allocate a new page for the child process
  4829 0000327E E82BFBFFFF          <1> 	call	allocate_page
  4830 00003283 721C                <1> 	jc	short cpt_p_err
  4831 00003285 57                  <1> 	push	edi
  4832 00003286 56                  <1> 	push	esi
  4833 00003287 89CE                <1> 	mov	esi, ecx
  4834 00003289 89C7                <1> 	mov	edi, eax
  4835 0000328B B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4836 00003290 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4837 00003292 5E                  <1> 	pop	esi
  4838 00003293 5F                  <1> 	pop	edi
  4839                              <1> 	; 
  4840                              <1> ; 24/12/2021
  4841                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4842                              <1> ;
  4843                              <1> ;	push	ebx
  4844                              <1> ;	push	eax
  4845                              <1> ;	mov	ebx, ebp
  4846                              <1> ;	; ebx = virtual address of the memory page
  4847                              <1> ;	call	add_to_swap_queue
  4848                              <1> ;	pop	eax
  4849                              <1> ;	pop	ebx
  4850                              <1> 	;
  4851                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4852 00003294 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4853                              <1> cpt_2:
  4854 00003296 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4855                              <1> 	;
  4856 00003297 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4857                              <1> 	;
  4858 0000329D 39D7                <1> 	cmp	edi, edx
  4859 0000329F 72D2                <1> 	jb	short cpt_0
  4860                              <1> cpt_p_err:
  4861 000032A1 59                  <1> 	pop	ecx
  4862 000032A2 5A                  <1> 	pop	edx
  4863 000032A3 5F                  <1> 	pop	edi
  4864 000032A4 5E                  <1> 	pop	esi
  4865                              <1> 	;pop	ebx
  4866 000032A5 58                  <1> 	pop	eax ; *
  4867                              <1> cpt_err:
  4868 000032A6 C3                  <1> 	retn
  4869                              <1> 
  4870                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4871                              <1> 
  4872                              <1> ;; Data:
  4873                              <1> 
  4874                              <1> ; 09/03/2015
  4875                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4876                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4877                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4878                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4879                              <1> ;swpd_next:  dd 0 ; next free page block
  4880                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2100                                  %include 'sysdefs.inc' ; 09/03/2015
  2101                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.4) - SYSDEFS.INC
  2102                              <1> ; Last Modification: 13/06/2022
  2103                              <1> ;
  2104                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2105                              <1> ; (Modified from 
  2106                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2107                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2108                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2109                              <1> ; ----------------------------------------------------------------------------
  2110                              <1> ;
  2111                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2112                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2113                              <1> ; <Bell Laboratories (17/3/1972)>
  2114                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2115                              <1> ;
  2116                              <1> ; ****************************************************************************
  2117                              <1> 
  2118                              <1> nproc 	equ	16  ; number of processes
  2119                              <1> nfiles 	equ	50
  2120                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2121                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2122                              <1> 
  2123                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2124                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2125                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2126                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2127                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2128                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2129                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2130                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2131                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2132                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2133                              <1> 	; '/core' dump file size = 32768 bytes
  2134                              <1>  
  2135                              <1> ; 08/03/2014 
  2136                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2137                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2138                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2139                              <1> 
  2140                              <1> ; 30/08/2013
  2141                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2142                              <1> 
  2143                              <1> ; 05/02/2014
  2144                              <1> ; process status
  2145                              <1> ;SFREE 	equ 0
  2146                              <1> ;SRUN	equ 1
  2147                              <1> ;SWAIT	equ 2
  2148                              <1> ;SZOMB	equ 3
  2149                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2150                              <1> 
  2151                              <1> ; 09/03/2015
  2152                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2153                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2154                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2155                              <1> 
  2156                              <1> ; 17/09/2015
  2157                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2158                              <1> 
  2159                              <1> ; 21/09/2015 (36) 
  2160                              <1> ; 01/07/2015 (35)
  2161                              <1> ; 14/07/2013 (0-34)
  2162                              <1> ; UNIX v1 system calls
  2163                              <1> _rele 	equ 0
  2164                              <1> _exit 	equ 1
  2165                              <1> _fork 	equ 2
  2166                              <1> _read 	equ 3
  2167                              <1> _write	equ 4
  2168                              <1> _open	equ 5
  2169                              <1> _close 	equ 6
  2170                              <1> _wait 	equ 7
  2171                              <1> _creat 	equ 8
  2172                              <1> _link 	equ 9
  2173                              <1> _unlink	equ 10
  2174                              <1> _exec	equ 11
  2175                              <1> _chdir	equ 12
  2176                              <1> _time 	equ 13
  2177                              <1> _mkdir 	equ 14
  2178                              <1> _chmod	equ 15
  2179                              <1> _chown	equ 16
  2180                              <1> _break	equ 17
  2181                              <1> _stat	equ 18
  2182                              <1> _seek	equ 19
  2183                              <1> _tell 	equ 20
  2184                              <1> _mount	equ 21
  2185                              <1> _umount	equ 22
  2186                              <1> _setuid	equ 23
  2187                              <1> _getuid	equ 24
  2188                              <1> _stime	equ 25
  2189                              <1> _quit	equ 26	
  2190                              <1> _intr	equ 27
  2191                              <1> _fstat	equ 28
  2192                              <1> _emt 	equ 29
  2193                              <1> _mdate 	equ 30
  2194                              <1> _stty 	equ 31
  2195                              <1> _gtty	equ 32
  2196                              <1> _ilgins	equ 33
  2197                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2198                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2199                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2200                              <1> 
  2201                              <1> %macro sys 1-4
  2202                              <1>     ; 13/04/2015
  2203                              <1>     ; Retro UNIX 386 v1 system call.		
  2204                              <1>     mov eax, %1
  2205                              <1>     %if %0 >= 2   
  2206                              <1>         mov ebx, %2
  2207                              <1>         %if %0 >= 3    
  2208                              <1>             mov ecx, %3
  2209                              <1>             %if %0 = 4
  2210                              <1>                mov edx, %4   
  2211                              <1>             %endif
  2212                              <1>         %endif
  2213                              <1>     %endif
  2214                              <1>     int 30h	   
  2215                              <1> %endmacro
  2216                              <1> 
  2217                              <1> ; 13/05/2015 - ERROR CODES
  2218                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2219                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2220                              <1> ; 14/05/2015
  2221                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2222                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2223                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2224                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2225                              <1> ; 16/05/2015		
  2226                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2227                              <1> ; 18/05/2015
  2228                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2229                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2230                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2231                              <1> ; 07/06/2015
  2232                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2233                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2234                              <1> ; 09/06/2015
  2235                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2236                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2237                              <1> ; 16/06/2015
  2238                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2239                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2240                              <1> ; 22/06/2015
  2241                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2242                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2243                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2244                              <1> ; 23/06/2015
  2245                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2246                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2247                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2248                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2249                              <1> ; 27/06/2015
  2250                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2251                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2252                              <1> ; 29/06/2015
  2253                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2254                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2255                              <1> ; 08/02/2022 
  2256                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2257                              <1> ; 10/10/2016
  2258                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2259                              <1> ; 18/05/2016
  2260                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2261                              <1> ; 15/10/2016
  2262                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2263                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2264                              <1> ; 16/10/2016
  2265                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2266                              <1> ; 08/02/2022
  2267                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2268                              <1> 
  2269                              <1> ; 13/06/2022
  2270                              <1> ; printer errors
  2271                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2272                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2273                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2274                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2275                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error
  2276                              <1> 
  2277                              <1> ; 26/08/2015
  2278                              <1> ; 24/07/2015
  2279                              <1> ; 24/06/2015
  2280                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2281                              <1> ; 01/07/2015
  2282                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2283                              <1> ; 24/12/2021
  2284                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2101                                  %include 'u0.s'        ; 15/03/2015
  2102                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS0.INC
  2103                              <1> ; Last Modification: 02/06/2022
  2104                              <1> ; ----------------------------------------------------------------------------
  2105                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2106                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2107                              <1> ;
  2108                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2109                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2110                              <1> ; <Bell Laboratories (17/3/1972)>
  2111                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2112                              <1> ;
  2113                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2114                              <1> ;
  2115                              <1> ; ****************************************************************************
  2116                              <1> 
  2117                              <1> sys_init:
  2118                              <1> 	; 26/02/2022
  2119                              <1> 	; 08/01/2022
  2120                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2121                              <1> 	; 18/10/2015
  2122                              <1> 	; 28/08/2015
  2123                              <1> 	; 24/08/2015
  2124                              <1> 	; 14/08/2015
  2125                              <1> 	; 24/07/2015 
  2126                              <1> 	; 02/07/2015
  2127                              <1> 	; 01/07/2015
  2128                              <1> 	; 23/06/2015
  2129                              <1> 	; 15/04/2015
  2130                              <1> 	; 13/03/2015
  2131                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2132                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2133                              <1> 	;
  2134                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2135                              <1> 	;
  2136                              <1> 	; 14/02/2014
  2137                              <1> 	; 14/07/2013
  2138                              <1> 	;;mov	ax, 41
  2139                              <1> 	; 24/12/2021
  2140                              <1> 	;xor	eax, eax
  2141                              <1> 	;mov	al, 41
  2142                              <1> 	;mov	[rootdir], ax
  2143                              <1> 	;mov	[u.cdir], ax
  2144                              <1> 	;;and	al, 1 ; 15/04/2015
  2145                              <1> 	;inc	al  ; ax = 1
  2146 000032A7 B001                <1> 	mov	al, 1
  2147 000032A9 A2[9B700000]        <1> 	mov	[u.uno], al
  2148                              <1> 	;mov	[mpid], ax
  2149                              <1> 	;mov	[p.pid], ax
  2150 000032AE A2[38700000]        <1> 	mov	[mpid], al
  2151 000032B3 A2[686D0000]        <1> 	mov	[p.pid], al	
  2152 000032B8 A2[C86D0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2153                              <1> 	; 24/12/2021
  2154 000032BD B029                <1> 	mov	al, 41
  2155                              <1> 	;mov	[rootdir], ax
  2156                              <1> 	;mov	[u.cdir], ax
  2157 000032BF A2[3A700000]        <1> 	mov	[rootdir], al
  2158 000032C4 A2[50700000]        <1> 	mov	[u.cdir], al
  2159                              <1> 	;
  2160 000032C9 B004                <1> 	mov	al, time_count ; 30/08/2013
  2161 000032CB A2[8E700000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2162                              <1> 	; 02/07/2015
  2163 000032D0 A1[886C0000]        <1> 	mov	eax, [k_page_dir]
  2164                              <1> 	;sub	eax, eax
  2165 000032D5 A3[A5700000]        <1> 	mov	[u.pgdir], eax ; reset
  2166                              <1> 	; 18/10/2015
  2167                              <1> 	;mov	[u.ppgdir], eax ; 0
  2168                              <1> 	; 26/02/2022
  2169                              <1>  	;call	epoch
  2170                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2171                              <1> 	; 17/07/2013
  2172 000032DA E884060000          <1> 	call 	bf_init ; buffer initialization
  2173                              <1> 	; 26/02/2022
  2174                              <1> 	; (save sysinit time on sb0)
  2175 000032DF E829030000          <1> 	call	epoch
  2176 000032E4 A3[987E0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2177                              <1> 	; 23/06/2015
  2178 000032E9 E8C0FAFFFF          <1> 	call	allocate_page
  2179                              <1> 	;;jc	error
  2180                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2181                              <1> 	; 24/12/2021
  2182 000032EE 7305                <1> 	jnc	short sysinit_1
  2183 000032F0 E989000000          <1> 	jmp	panic
  2184                              <1> sysinit_1:
  2185 000032F5 A3[9C700000]        <1> 	mov	[u.upage], eax ; user structure page	
  2186 000032FA A3[D86D0000]        <1> 	mov	[p.upage], eax
  2187                              <1> 	;
  2188 000032FF E81BFBFFFF          <1> 	call	clear_page
  2189                              <1> 	;
  2190                              <1> 	; 14/08/2015
  2191 00003304 FA                  <1> 	cli
  2192                              <1> 	; 14/03/2015
  2193                              <1> 	; 17/01/2014
  2194 00003305 E8D0010000          <1> 	call	sp_init ; serial port initialization
  2195                              <1> 	; 14/08/2015
  2196 0000330A FB                  <1> 	sti
  2197                              <1> 	;
  2198                              <1> 	; 30/06/2015
  2199                              <1> 	;mov	esi, kernel_init_ok_msg
  2200                              <1> 	;call 	print_msg
  2201                              <1> 	;
  2202 0000330B 30DB                <1> 	xor	bl, bl ; video page 0
  2203                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2204 0000330D E8450F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2205 00003312 FEC3                <1> 	inc	bl
  2206 00003314 80FB08              <1> 	cmp	bl, 8
  2207 00003317 72F4                <1> 	jb	short vp_clr_nxt
  2208                              <1> 	;
  2209                              <1> 	; 24/07/2015
  2210                              <1> 	;push    KDATA
  2211                              <1>         ;push    esp
  2212                              <1> 	;mov	[tss.esp0], esp
  2213                              <1>         ;mov     word [tss.ss0], KDATA
  2214                              <1> 	;
  2215                              <1> 	; 08/01/2022
  2216                              <1> 	; 24/08/2015
  2217                              <1> 	;; temporary (01/07/2015)
  2218                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2219                              <1> 			       ; it is not needed here !
  2220                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2221 00003319 FE0D[41700000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2222                              <1> 			      ; 0 = executing a system call
  2223                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2224                              <1> 	;
  2225                              <1> 	;;; 06/08/2015
  2226                              <1> 	;;;call	getch ; wait for a key stroke
  2227                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2228                              <1> ;;sys_init_msg_wait:
  2229                              <1> ;;	push 	ecx
  2230                              <1> ;;	mov	al, 1
  2231                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2232                              <1> ;;	call	getc_n
  2233                              <1> ;;	pop	ecx
  2234                              <1> ;;	jnz	short sys_init_msg_ok
  2235                              <1> ;;	loop	sys_init_msg_wait
  2236                              <1> 	;
  2237                              <1> ;;sys_init_msg_ok:
  2238                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2239 0000331F 6A10                <1> 	push	KDATA ; ss
  2240 00003321 54                  <1> 	push	esp
  2241 00003322 9C                  <1> 	pushfd
  2242 00003323 6A08                <1> 	push	KCODE ; cs
  2243 00003325 68[52330000]        <1> 	push	init_exec ; eip
  2244 0000332A 8925[44700000]      <1> 	mov	[u.sp], esp
  2245 00003330 1E                  <1> 	push	ds
  2246 00003331 06                  <1> 	push	es
  2247 00003332 0FA0                <1> 	push	fs
  2248 00003334 0FA8                <1> 	push	gs	
  2249 00003336 60                  <1> 	pushad
  2250 00003337 8925[48700000]      <1> 	mov	[u.usp], esp
  2251 0000333D E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2252                              <1> 		      ; and interrupt return components (for IRET)
  2253 00003342 61                  <1> 	popad
  2254 00003343 6658                <1> 	pop	ax ; gs
  2255 00003345 6658                <1> 	pop	ax ; fs
  2256 00003347 6658                <1> 	pop	ax ; es
  2257 00003349 6658                <1> 	pop	ax ; ds	
  2258 0000334B 58                  <1> 	pop	eax ; eip (init_exec)
  2259 0000334C 6658                <1> 	pop	ax ; cs (KCODE)
  2260 0000334E 58                  <1> 	pop	eax ; E-FLAGS
  2261 0000334F 58                  <1> 	pop	eax ; esp
  2262 00003350 6658                <1> 	pop	ax ; ss (KDATA)
  2263                              <1> 	;
  2264                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2265                              <1> 	;xor	eax, eax ; 0
  2266                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2267                              <1> 	;
  2268                              <1> 	; 02/07/2015
  2269                              <1> 	; [u.pgdir ] = [k_page_dir]
  2270                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2271                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2272                              <1> init_exec:
  2273                              <1> 	; 13/03/2013
  2274                              <1> 	; 24/07/2013
  2275 00003352 BB[74330000]        <1> 	mov	ebx, init_file
  2276 00003357 B9[6C330000]        <1> 	mov	ecx, init_argp
  2277                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2278                              <1> 	; ECX contains address of argument list pointer
  2279                              <1> 	;
  2280                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2281                              <1> 			      ; 0 = executing a system call
  2282                              <1> 	sys	_exec  ; execute file
  2202                              <2> 
  2203                              <2> 
  2204 0000335C B80B000000          <2>  mov eax, %1
  2205                              <2>  %if %0 >= 2
  2206                              <2>  mov ebx, %2
  2207                              <2>  %if %0 >= 3
  2208                              <2>  mov ecx, %3
  2209                              <2>  %if %0 = 4
  2210                              <2>  mov edx, %4
  2211                              <2>  %endif
  2212                              <2>  %endif
  2213                              <2>  %endif
  2214 00003361 CD30                <2>  int 30h
  2283 00003363 7319                <1> 	jnc	short panic
  2284                              <1> 	;
  2285 00003365 BE[9C690000]        <1> 	mov	esi, etc_init_err_msg
  2286                              <1> 	; 08/01/2022
  2287                              <1> 	;call 	print_msg
  2288 0000336A EB17                <1> 	jmp	short key_to_reboot
  2289                              <1> 
  2290                              <1> ;align 4
  2291                              <1> init_argp:
  2292 0000336C [74330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2293                              <1> init_file:
  2294                              <1> 	; 24/08/2015
  2295 00003374 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2295 0000337D 00                  <1>
  2296                              <1> panic:
  2297                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2298                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2299 0000337E BE[81690000]        <1> 	mov 	esi, panic_msg
  2300                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2301 00003383 E819000000          <1> 	call 	print_msg
  2302                              <1> ;key_to_reboot:
  2303                              <1> 	; 15/11/2015
  2304 00003388 E8172D0000          <1> 	call 	getch 
  2305                              <1> 		; wait for a character from the current tty
  2306                              <1> 	;
  2307 0000338D B00A                <1> 	mov	al, 0Ah
  2308 0000338F 8A1D[B66C0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2309 00003395 B407                <1> 	mov	ah, 07h ; Black background, 
  2310                              <1> 			; light gray forecolor
  2311 00003397 E825E0FFFF          <1> 	call 	write_tty
  2312 0000339C E9C4DCFFFF          <1> 	jmp	cpu_reset 
  2313                              <1> 
  2314                              <1> print_msg:
  2315                              <1> 	; 01/07/2015
  2316                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2317                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2318                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2319                              <1> 	;
  2320                              <1> 	;
  2321 000033A1 AC                  <1> 	lodsb
  2322                              <1> pmsg1:
  2323 000033A2 56                  <1> 	push 	esi
  2324 000033A3 0FB61D[B66C0000]    <1> 	movzx	ebx, byte [ptty]
  2325 000033AA B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2326 000033AC E810E0FFFF          <1> 	call 	write_tty
  2327 000033B1 5E                  <1> 	pop	esi
  2328 000033B2 AC                  <1> 	lodsb
  2329 000033B3 20C0                <1> 	and 	al, al
  2330 000033B5 75EB                <1> 	jnz 	short pmsg1
  2331 000033B7 C3                  <1> 	retn
  2332                              <1> 	
  2333                              <1> ctrlbrk:
  2334                              <1> 	; 04/02/2022
  2335                              <1> 	; 01/02/2022
  2336                              <1> 	; 12/11/2015
  2337                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2338                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2339                              <1> 	;
  2340                              <1> 	; INT 1Bh (control+break) handler
  2341                              <1> 	;
  2342                              <1>       	; Retro Unix 8086 v1 feature only!
  2343                              <1>       	;
  2344 000033B8 66833D[90700000]00  <1> 	cmp 	word [u.intr], 0
  2345 000033C0 764B                <1> 	jna 	short cbrk4
  2346                              <1> cbrk0:
  2347                              <1> 	; 12/11/2015
  2348                              <1> 	; 06/12/2013
  2349 000033C2 66833D[92700000]00  <1> 	cmp 	word [u.quit], 0
  2350 000033CA 7441                <1> 	jz	short cbrk4
  2351                              <1> 	;
  2352                              <1> 	; 20/09/2013	
  2353                              <1> 	;push 	ax
  2354                              <1> 	; 01/02/2022
  2355 000033CC 50                  <1> 	push	eax
  2356                              <1> 
  2357                              <1> 	; 04/02/2022
  2358                              <1> 	; (repetitive ctrl+brk check) 
  2359 000033CD 66A1[92700000]      <1> 	mov	ax, [u.quit]
  2360 000033D3 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2361 000033D5 7435                <1> 	jz	short cbrk3
  2362                              <1> 
  2363                              <1> 	; 20/09/2013
  2364 000033D7 A0[B66C0000]        <1> 	mov	al, [ptty]
  2365                              <1> 	;
  2366                              <1> 	; 12/11/2015
  2367                              <1> 	;
  2368                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2369                              <1> 	; or ctrl+break from console (pseudo) tty
  2370                              <1> 	; (!redirection!)
  2371                              <1> 	;
  2372 000033DC 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2373 000033DE 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2374                              <1> 	;	
  2375                              <1> 	; Serial port interrupt handler sets [ptty]
  2376                              <1> 	; to the port's tty number (as temporary).
  2377                              <1> 	;
  2378                              <1> 	; If active process is using a stdin or 
  2379                              <1> 	; stdout redirection (by the shell),
  2380                              <1>         ; console tty keyboard must be available
  2381                              <1> 	; to terminate running process,
  2382                              <1> 	; in order to prevent a deadlock. 
  2383                              <1> 	;
  2384 000033E0 52                  <1> 	push	edx
  2385 000033E1 0FB615[9B700000]    <1> 	movzx	edx, byte [u.uno]
  2386 000033E8 3A82[A76D0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2387 000033EE 5A                  <1> 	pop	edx
  2388 000033EF 7412                <1> 	je	short cbrk2
  2389                              <1> cbrk1:
  2390 000033F1 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2391                              <1> 	; 06/12/2013
  2392 000033F3 3A05[7C700000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2393 000033F9 7408                <1> 	je	short cbrk2	
  2394 000033FB 3A05[7D700000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2395 00003401 7509                <1> 	jne	short cbrk3	
  2396                              <1> cbrk2:
  2397                              <1> 	;; 06/12/2013
  2398                              <1> 	;mov	ax, [u.quit]
  2399                              <1> 	;and	ax, ax
  2400                              <1> 	;jz	short cbrk3
  2401                              <1> 	;
  2402                              <1> 	;xor	ax, ax ; 0
  2403                              <1> 	;dec	ax
  2404                              <1> 	; 01/02/2022
  2405 00003403 31C0                <1> 	xor	eax, eax ; 0
  2406 00003405 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2407                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2408 00003406 66A3[92700000]      <1> 	mov	[u.quit], ax
  2409                              <1> cbrk3:
  2410                              <1> 	;pop	ax
  2411                              <1> 	; 01/02/2022
  2412 0000340C 58                  <1> 	pop	eax
  2413                              <1> cbrk4:
  2414 0000340D C3                  <1> 	retn
  2415                              <1> 
  2416                              <1> com2_int:
  2417                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2418                              <1> 	; 07/11/2015 
  2419                              <1> 	; 24/10/2015
  2420                              <1> 	; 23/10/2015
  2421                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2422                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2423                              <1> 	; < serial port 2 interrupt handler >
  2424                              <1> 	;
  2425 0000340E 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2426                              <1> 	;;push	eax
  2427                              <1> 	; 08/01/2022
  2428 00003411 29C0                <1> 	sub	eax, eax
  2429 00003413 B009                <1> 	mov	al, 9
  2430                              <1> 	;mov	ax, 9
  2431 00003415 EB07                <1> 	jmp	short comm_int
  2432                              <1> com1_int:
  2433                              <1> 	; 07/11/2015
  2434                              <1> 	; 24/10/2015
  2435 00003417 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2436                              <1> 	; 23/10/2015
  2437                              <1> 	;push	eax
  2438                              <1> 	; 08/01/2022
  2439 0000341A 29C0                <1> 	sub	eax, eax
  2440 0000341C B008                <1> 	mov	al, 8
  2441                              <1> 	;mov	ax, 8
  2442                              <1> comm_int:
  2443                              <1> 	; 08/01/2022
  2444                              <1> 	; 20/11/2015
  2445                              <1> 	; 18/11/2015
  2446                              <1> 	; 17/11/2015
  2447                              <1> 	; 16/11/2015
  2448                              <1> 	; 09/11/2015
  2449                              <1> 	; 08/11/2015
  2450                              <1> 	; 07/11/2015
  2451                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2452                              <1> 	; 01/11/2015
  2453                              <1> 	; 26/10/2015
  2454                              <1> 	; 23/10/2015
  2455 0000341E 53                  <1> 	push	ebx
  2456 0000341F 56                  <1> 	push	esi
  2457 00003420 57                  <1> 	push	edi
  2458 00003421 1E                  <1> 	push 	ds
  2459 00003422 06                  <1> 	push 	es
  2460                              <1> 	; 18/11/2015
  2461 00003423 0F20DB              <1> 	mov	ebx, cr3
  2462 00003426 53                  <1> 	push	ebx ; ****
  2463                              <1> 	;
  2464 00003427 51                  <1> 	push	ecx ; ***
  2465 00003428 52                  <1> 	push	edx ; **
  2466                              <1> 	;
  2467 00003429 BB10000000          <1> 	mov	ebx, KDATA
  2468 0000342E 8EDB                <1> 	mov	ds, bx
  2469 00003430 8EC3                <1> 	mov	es, bx
  2470                              <1> 	;
  2471 00003432 8B0D[886C0000]      <1> 	mov	ecx, [k_page_dir]
  2472 00003438 0F22D9              <1> 	mov	cr3, ecx
  2473                              <1> 	; 20/11/2015
  2474                              <1> 	; Interrupt identification register
  2475 0000343B 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2476                              <1> 	;
  2477 0000343F 3C08                <1> 	cmp 	al, 8 
  2478 00003441 7702                <1> 	ja 	short com_i0
  2479                              <1> 	;
  2480                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2481                              <1> 	; 20/11/2015
  2482                              <1> 	; 17/11/2015
  2483                              <1> 	; 16/11/2015
  2484                              <1> 	; 15/11/2015
  2485                              <1> 	; 24/10/2015
  2486                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2487                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2488                              <1> 	; < serial port 1 interrupt handler >
  2489                              <1> 	;
  2490 00003443 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2491                              <1> com_i0:
  2492                              <1> 	;push	eax ; *
  2493                              <1> 	; 07/11/2015
  2494 00003445 A2[F66C0000]        <1> 	mov 	byte [ccomport], al
  2495                              <1> 	; 09/11/2015
  2496                              <1> 	;movzx	ebx, ax ; 8 or 9
  2497                              <1> 	; 08/01/2022
  2498 0000344A 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2499                              <1> 	; 17/11/2015
  2500                              <1>  	; reset request for response status
  2501 0000344C 88A3[EC6C0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2502                              <1> 	;
  2503                              <1> 	; 20/11/2015
  2504 00003452 EC                  <1> 	in	al, dx		; read interrupt id. register
  2505 00003453 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2506 00003455 2404                <1> 	and	al, 4		; received data available?	
  2507 00003457 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2508                              <1> 	;
  2509                              <1> 	; 20/11/2015
  2510 00003459 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2511 0000345C EC                  <1> 	in	al, dx     	; read character
  2512                              <1> 	;JMP	$+2	   	; I/O DELAY
  2513                              <1> 	; 08/11/2015
  2514                              <1> 	; 07/11/2015
  2515 0000345D 89DE                <1> 	mov	esi, ebx 
  2516 0000345F 89DF                <1> 	mov	edi, ebx
  2517 00003461 81C6[F06C0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2518 00003467 81C7[F26C0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2519 0000346D 8806                <1> 	mov	[esi], al ; received char (current char)
  2520                              <1> 	; query
  2521 0000346F 20C0                <1> 	and	al, al
  2522 00003471 7527                <1> 	jnz	short com_i2
  2523                              <1>    	; response
  2524                              <1> 	; 17/11/2015
  2525                              <1> 	; set request for response status
  2526 00003473 FE83[EC6C0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2527                              <1> 	;
  2528 00003479 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2529 0000347D EC                  <1> 	in	al, dx	   	; read line status register 
  2530 0000347E EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2531 00003480 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2532 00003482 7445                <1> 	jz	short com_eoi 	; no
  2533 00003484 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2534 00003486 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2535 0000348A EE                  <1> 	out	dx, al	   	; send on serial port
  2536                              <1> 	; 17/11/2015
  2537 0000348B 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2538 0000348E 7502                <1> 	jne 	short com_i1    ; no
  2539 00003490 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2540                              <1> com_i1:
  2541                              <1> 	; 17/11/2015
  2542                              <1> 	; reset request for response status (again)
  2543 00003492 FE8B[EC6C0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2544 00003498 EB2F                <1> 	jmp	short com_eoi
  2545                              <1> com_i2:	
  2546                              <1> 	; 08/11/2015
  2547 0000349A 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2548 0000349C 7417                <1> 	je	short com_i3	; (check for response signal)
  2549                              <1> 	; 07/11/2015
  2550 0000349E 3C04                <1> 	cmp	al, 04h	; EOT
  2551 000034A0 751C                <1> 	jne	short com_i4	
  2552                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2553                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2554                              <1> 	; 08/11/2015
  2555                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2556 000034A2 861D[B66C0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2557 000034A8 E80BFFFFFF          <1> 	call 	ctrlbrk
  2558 000034AD 861D[B66C0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2559                              <1> 	;mov	al, 04h ; EOT
  2560                              <1> 	; 08/11/2015
  2561 000034B3 EB09                <1> 	jmp	short com_i4	
  2562                              <1> com_i3:
  2563                              <1> 	; 08/11/2015
  2564                              <1> 	; If 0FFh has been received just after a query
  2565                              <1> 	; (schar, ZERO), it is a response signal.
  2566                              <1> 	; 17/11/2015
  2567 000034B5 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2568 000034B8 7704                <1> 	ja	short com_i4 ; no
  2569                              <1> 	; reset query status (schar)
  2570 000034BA 8807                <1> 	mov	[edi], al ; 0FFh
  2571 000034BC FEC0                <1> 	inc	al ; 0
  2572                              <1> com_i4:
  2573                              <1> 	; 27/07/2014
  2574                              <1> 	; 09/07/2014
  2575 000034BE D0E3                <1> 	shl	bl, 1	
  2576 000034C0 81C3[B86C0000]      <1> 	add	ebx, ttychr
  2577                              <1> 	; 23/07/2014 (always overwrite)
  2578                              <1> 	;;cmp	word [ebx], 0
  2579                              <1> 	;;ja	short com_eoi
  2580                              <1> 	;
  2581 000034C6 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2582                              <1> 			    ; scan code = 0
  2583                              <1> com_eoi:
  2584                              <1> 	;mov	al, 20h
  2585                              <1> 	;out	20h, al	   ; end of interrupt
  2586                              <1> 	;
  2587                              <1> 	; 07/11/2015
  2588                              <1>       	;pop	eax ; *
  2589 000034C9 A0[F66C0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2590                              <1> 	; al = tty number (8 or 9)
  2591 000034CE E8FA1A0000          <1>         call	wakeup
  2592                              <1> com_iret:
  2593                              <1> 	; 23/10/2015
  2594 000034D3 5A                  <1> 	pop	edx ; **
  2595 000034D4 59                  <1> 	pop	ecx ; ***
  2596                              <1> 	; 18/11/2015
  2597                              <1> 	;pop	eax ; ****
  2598                              <1> 	;mov	cr3, eax
  2599                              <1> 	;jmp	iiret
  2600 000034D5 E9C9D4FFFF          <1> 	jmp	iiretp
  2601                              <1> 
  2602                              <1> ;iiretp: ; 01/09/2015
  2603                              <1> ;	; 28/08/2015
  2604                              <1> ;	pop	eax ; (*) page directory
  2605                              <1> ;	mov	cr3, eax
  2606                              <1> ;iiret:
  2607                              <1> ;	; 22/08/2014
  2608                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2609                              <1> ;	out	20h, al	; 8259 PORT
  2610                              <1> ;	;
  2611                              <1> ;	pop	es
  2612                              <1> ;	pop	ds
  2613                              <1> ;	pop	edi
  2614                              <1> ;	pop	esi
  2615                              <1> ;	pop	ebx ; 29/08/2014
  2616                              <1> ;	pop 	eax
  2617                              <1> ;	iretd
  2618                              <1> 
  2619                              <1> sp_init:
  2620                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2621                              <1> 	; 07/11/2015
  2622                              <1> 	; 29/10/2015
  2623                              <1> 	; 26/10/2015
  2624                              <1> 	; 23/10/2015
  2625                              <1> 	; 29/06/2015
  2626                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2627                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2628                              <1> 	; Initialization of Serial Port Communication Parameters
  2629                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2630                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2631                              <1> 	;
  2632                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2633                              <1> 	;
  2634                              <1> 	; INPUT:  (29/06/2015)
  2635                              <1> 	;	AL = 0 for COM1
  2636                              <1> 	;	     1 for COM2
  2637                              <1> 	;	AH = Communication parameters	
  2638                              <1> 	;
  2639                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2640                              <1> 	;	Bit	4	3	2	1	0
  2641                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2642                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2643                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2644                              <1> 	;		11 = even
  2645                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2646                              <1> 	;		Retro UNIX 386 v1 feature only !
  2647                              <1> 	;	Bit	7    6    5  | Baud rate
  2648                              <1> 	;		------------------------
  2649                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2650                              <1> 	;		0    0    1  | 9600 (12)
  2651                              <1> 	;		0    1    0  | 19200 (6) 
  2652                              <1> 	;		0    1	  1  | 38400 (3) 
  2653                              <1> 	;		1    0	  0  | 14400 (8)
  2654                              <1> 	;		1    0	  1  | 28800 (4)
  2655                              <1> 	;		1    1    0  | 57600 (2)
  2656                              <1> 	;		1    1    1  | 115200 (1) 	
  2657                              <1> 	
  2658                              <1> 	; References:	
  2659                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2660                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2661                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2662                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2663                              <1> 	;
  2664                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2665                              <1> 	;
  2666 000034DA BB[F26C0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2667 000034DF 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2668                              <1> 	; 29/10/2015
  2669 000034E3 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2670 000034E7 E84F000000          <1> 	call	sp_i3	; call A4	
  2671 000034EC A880                <1> 	test	al, 80h
  2672 000034EE 740E                <1> 	jz	short sp_i0 ; OK..
  2673                              <1> 		; Error !
  2674                              <1> 	;mov	dx, 3F8h
  2675 000034F0 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2676                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2677                              <1> 	; 08/01/2022
  2678 000034F3 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2679 000034F5 E841000000          <1> 	call	sp_i3	; call A4	
  2680 000034FA A880                <1> 	test	al, 80h
  2681 000034FC 7508                <1> 	jnz	short sp_i1
  2682                              <1> sp_i0:
  2683                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2684                              <1>         ; (INT 14h initialization code disables interrupts.)
  2685                              <1> 	;
  2686 000034FE C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2687 00003501 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2688                              <1> sp_i1:
  2689 00003506 43                  <1> 	inc	ebx
  2690 00003507 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2691                              <1> 	; 29/10/2015
  2692                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2693                              <1> 	; 08/01/2022
  2694 0000350B B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2695 0000350D E829000000          <1> 	call	sp_i3	; call A4	
  2696 00003512 A880                <1> 	test	al, 80h
  2697 00003514 740E                <1> 	jz	short sp_i2 ; OK..
  2698                              <1> 		; Error !
  2699                              <1> 	;mov	dx, 2F8h
  2700 00003516 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2701                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2702                              <1> 	; 08/01/2022
  2703 00003519 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2704 0000351B E81B000000          <1> 	call	sp_i3	; call A4	
  2705 00003520 A880                <1> 	test	al, 80h
  2706 00003522 7516                <1> 	jnz	short sp_i7
  2707                              <1> sp_i2:
  2708 00003524 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2709                              <1> sp_i6:
  2710                              <1> 	;; COM2 - enabling IRQ 3
  2711                              <1> 	; 08/01/2022
  2712 00003527 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2713                              <1> 	; 07/11/2015
  2714                              <1> 	; 26/10/2015
  2715                              <1> 	;pushf
  2716                              <1> 	;cli
  2717                              <1> 	;;
  2718                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2719                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2720                              <1> 	;in	al, dx 	   		; read register
  2721                              <1> 	;JMP	$+2	   		; I/O DELAY
  2722                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2723                              <1> 	;out	dx, al     		; write back to register
  2724                              <1> 	;JMP	$+2	   		; I/O DELAY
  2725                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2726                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2727                              <1> 	;in	al, dx     		; read register
  2728                              <1> 	;JMP	$+2	   		; I/O DELAY
  2729                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2730                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2731                              <1> 	;out	dx, al 	   		; write back to register
  2732                              <1> 	;JMP	$+2        		; I/O DELAY
  2733                              <1> 	;in	al, 21h    		; read interrupt mask register
  2734                              <1> 	;JMP	$+2	   		; I/O DELAY
  2735                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2736                              <1> 	;out	21h, al    		; write back to register
  2737                              <1> 	;
  2738                              <1> 	; 08/01/2022
  2739 00003529 9C                  <1> 	pushf
  2740 0000352A E8AA000000          <1> 	call	sp_i8
  2741                              <1> 	; 23/10/2015
  2742 0000352F B8[0E340000]        <1> 	mov 	eax, com2_int
  2743 00003534 A3[C2390000]        <1> 	mov	[com2_irq3], eax
  2744                              <1> 	; 26/10/2015
  2745 00003539 9D                  <1> 	popf	
  2746                              <1> sp_i7:
  2747 0000353A C3                  <1> 	retn
  2748                              <1> 
  2749                              <1> sp_i3:
  2750                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2751                              <1> 	; 28/10/2015
  2752 0000353B FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2753 0000353D B000                <1> 	mov	al, 0
  2754 0000353F EE                  <1> 	out	dx, al			; disable serial port interrupt
  2755 00003540 EB00                <1> 	JMP	$+2			; I/O DELAY
  2756 00003542 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2757 00003545 B080                <1> 	mov	al, 80h			
  2758 00003547 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2759                              <1> 	;-----	SET BAUD RATE DIVISOR
  2760                              <1> 	; 26/10/2015
  2761 00003548 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2762                              <1> 					; of the divisor value
  2763 0000354B 88C8                <1> 	mov	al, cl	; 1
  2764 0000354D EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2765                              <1> 					; 2 = 57600 baud
  2766                              <1> 					; 3 = 38400 baud
  2767                              <1> 					; 6 = 19200 baud
  2768                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2769 0000354E EB00                <1> 	JMP	$+2			; I/O DELAY
  2770 00003550 28C0                <1> 	sub	al, al
  2771 00003552 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2772                              <1> 					; of the divisor value
  2773 00003554 EE                  <1> 	out	dx, al ; 0
  2774 00003555 EB00                <1> 	JMP	$+2			; I/O DELAY
  2775                              <1> 	;	
  2776 00003557 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2777                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2778 00003559 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2779 0000355C EE                  <1> 	out	dx, al			
  2780 0000355D EB00                <1> 	JMP	$+2			; I/O DELAY
  2781                              <1> 	; 29/10/2015
  2782 0000355F FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2783 00003561 30C0                <1> 	xor	al, al			; 0
  2784 00003563 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2785 00003564 EB00                <1> 	JMP	$+2	
  2786                              <1> sp_i4:
  2787                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2788                              <1> 	; 29/06/2015 (line status after modem status)
  2789 00003566 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2790                              <1> sp_i4s:
  2791 00003569 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2792 0000356A EB00                <1> 	JMP	$+2			; I/O DELAY
  2793 0000356C 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2794 0000356E FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2795                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2796 00003570 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2797                              <1> 	; AL = Line status, AH = Modem status
  2798 00003571 C3                  <1> 	retn
  2799                              <1> 
  2800                              <1> sp_status:
  2801                              <1> 	; 29/06/2015
  2802                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2803                              <1> 	; Get serial port status
  2804 00003572 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2805 00003576 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2806                              <1> 					; dx = 2FEh for COM2
  2807 00003578 EBEF                <1> 	jmp	short sp_i4s
  2808                              <1> 
  2809                              <1> sp_setp: ; Set serial port communication parameters
  2810                              <1> 	; 08/01/2022
  2811                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2812                              <1> 	; 07/11/2015
  2813                              <1> 	; 29/10/2015
  2814                              <1> 	; 29/06/2015
  2815                              <1> 	; Retro UNIX 386 v1 feature only !	
  2816                              <1> 	;
  2817                              <1> 	; INPUT:
  2818                              <1> 	;	AL = 0 for COM1
  2819                              <1> 	;	     1 for COM2
  2820                              <1> 	;	AH = Communication parameters (*)
  2821                              <1> 	; OUTPUT:
  2822                              <1> 	;	CL = Line status
  2823                              <1> 	;	CH = Modem status
  2824                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2825                              <1> 	;		 'invalid parameter !' 
  2826                              <1> 	;		 	 or
  2827                              <1> 	;		 'device not ready !' error
  2828                              <1> 	;	
  2829                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2830                              <1> 	;	Bit	4	3	2	1	0
  2831                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2832                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2833                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2834                              <1> 	;		11 = even
  2835                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2836                              <1> 	;		Retro UNIX 386 v1 feature only !
  2837                              <1> 	;	Bit	7    6    5  | Baud rate
  2838                              <1> 	;		------------------------
  2839                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2840                              <1> 	;		0    0    1  | 9600 (12)
  2841                              <1> 	;		0    1    0  | 19200 (6) 
  2842                              <1> 	;		0    1	  1  | 38400 (3) 
  2843                              <1> 	;		1    0	  0  | 14400 (8)
  2844                              <1> 	;		1    0	  1  | 28800 (4)
  2845                              <1> 	;		1    1    0  | 57600 (2)
  2846                              <1> 	;		1    1    1  | 115200 (1) 
  2847                              <1> 	;
  2848                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2849                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2850                              <1> 	;
  2851                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2852                              <1> 	;
  2853 0000357A 66BAF803            <1> 	mov	dx, 3F8h
  2854 0000357E BB[F26C0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2855 00003583 3C01                <1> 	cmp	al, 1
  2856 00003585 7770                <1> 	ja 	short sp_invp_err
  2857 00003587 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2858 00003589 FECE                <1> 	dec	dh ; 2F8h
  2859 0000358B 43                  <1> 	inc	ebx ; COM2 control byte offset
  2860                              <1> sp_setp1:
  2861                              <1> 	; 29/10/2015
  2862 0000358C 8823                <1> 	mov	[ebx], ah
  2863 0000358E 0FB6CC              <1> 	movzx 	ecx, ah
  2864 00003591 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2865 00003594 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2866 00003597 8A81[06360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2867 0000359D 6689C1              <1> 	mov	cx, ax
  2868 000035A0 E896FFFFFF          <1> 	call	sp_i3
  2869 000035A5 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2870 000035A8 A880                <1> 	test	al, 80h
  2871 000035AA 740F                <1> 	jz	short sp_setp2
  2872 000035AC C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2873                              <1> stp_dnr_err:
  2874 000035AF C705[A1700000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2874 000035B7 0000                <1>
  2875                              <1> 	; CL = Line status, CH = Modem status
  2876 000035B9 F9                  <1> 	stc
  2877 000035BA C3                  <1> 	retn
  2878                              <1> sp_setp2:
  2879 000035BB 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2880                              <1>         ;jna	sp_i6
  2881                              <1> 		      ; COM1 (3F?h)
  2882                              <1> 	; 24/12/2021
  2883 000035BE 7705                <1> 	ja	short sp_i5
  2884 000035C0 E962FFFFFF          <1> 	jmp	sp_i6
  2885                              <1> sp_i5: 
  2886                              <1> 	; 08/01/2022
  2887 000035C5 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2888                              <1> 	; 07/11/2015
  2889                              <1> 	; 26/10/2015
  2890                              <1> 	; 29/06/2015
  2891                              <1> 	;
  2892                              <1> 	;; COM1 - enabling IRQ 4
  2893                              <1> 	;pushf
  2894                              <1> 	;cli
  2895                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2896                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2897                              <1> 	;in	al, dx 	   		; read register
  2898                              <1> 	;JMP	$+2			; I/O DELAY
  2899                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2900                              <1> 	;out	dx, al     		; write back to register
  2901                              <1> 	;JMP	$+2			; I/O DELAY
  2902                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2903                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2904                              <1> 	;in	al, dx     		; read register
  2905                              <1> 	;JMP	$+2			; I/O DELAY
  2906                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2907                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2908                              <1> 	;out	dx, al 	   		; write back to register
  2909                              <1> 	;JMP	$+2        		; I/O DELAY
  2910                              <1> 	;in	al, 21h    		; read interrupt mask register
  2911                              <1> 	;JMP	$+2			; I/O DELAY
  2912                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2913                              <1> 	;out	21h, al    		; write back to register
  2914                              <1> 	;
  2915                              <1> 	; 08/01/2022
  2916 000035C7 9C                  <1> 	pushf
  2917 000035C8 E80C000000          <1> 	call	sp_i8
  2918                              <1> 	; 23/10/2015
  2919 000035CD B8[17340000]        <1> 	mov 	eax, com1_int
  2920 000035D2 A3[BE390000]        <1> 	mov	[com1_irq4], eax
  2921                              <1> 	; 26/10/2015
  2922 000035D7 9D                  <1> 	popf
  2923 000035D8 C3                  <1> 	retn
  2924                              <1> 
  2925                              <1> sp_i8:
  2926                              <1> 	; 08/01/2022
  2927                              <1> 	;pushf
  2928 000035D9 FA                  <1> 	cli
  2929                              <1> 	;
  2930                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2931 000035DA B2FC                <1> 	mov	dl, 0FCh
  2932 000035DC EC                  <1> 	in	al, dx 	   		; read register
  2933 000035DD EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2934 000035DF 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2935 000035E1 EE                  <1> 	out	dx, al     		; write back to register
  2936 000035E2 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2937                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2938 000035E4 B2F9                <1> 	mov	dl, 0F9h
  2939 000035E6 EC                  <1> 	in	al, dx     		; read register
  2940 000035E7 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2941                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2942 000035E9 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2943 000035EB EE                  <1> 	out	dx, al 	   		; write back to register
  2944 000035EC EB00                <1> 	JMP	$+2        		; I/O DELAY
  2945 000035EE E421                <1> 	in	al, 21h    		; read interrupt mask register
  2946 000035F0 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2947                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2948 000035F2 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2949 000035F4 E621                <1> 	out	21h, al    		; write back to register
  2950                              <1> 	;
  2951                              <1> 	;popf	
  2952 000035F6 C3                  <1> 	retn
  2953                              <1> 
  2954                              <1> sp_invp_err:
  2955 000035F7 C705[A1700000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2955 000035FF 0000                <1>
  2956 00003601 31C9                <1> 	xor	ecx, ecx
  2957 00003603 49                  <1> 	dec	ecx ; 0FFFFh
  2958 00003604 F9                  <1> 	stc
  2959 00003605 C3                  <1> 	retn
  2960                              <1> 
  2961                              <1> ; 29/10/2015
  2962                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2963 00003606 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2964                              <1> 
  2965                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2966                              <1> epoch:
  2967                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2968                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2969                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2970                              <1> 	; 'epoch' procedure prototype: 
  2971                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2972                              <1> 	; 14/11/2012
  2973                              <1> 	; unixboot.asm (boot file configuration)
  2974                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2975                              <1> 	; 21/7/2012
  2976                              <1> 	; 15/7/2012
  2977                              <1> 	; 14/7/2012		
  2978                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2979                              <1> 	; compute current date and time as UNIX Epoch/Time
  2980                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2981                              <1> 	;
  2982                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2983                              <1> 	;
  2984 0000360D E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2985 00003612 86E9                <1>         xchg 	ch,cl
  2986 00003614 66890D[F4690000]    <1>         mov 	[hour], cx
  2987 0000361B 86F2                <1>         xchg 	dh,dl
  2988 0000361D 668915[F6690000]    <1>         mov 	[second], dx
  2989                              <1> 	;
  2990 00003624 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2991 00003629 86E9                <1>         xchg 	ch,cl
  2992 0000362B 66890D[F0690000]    <1>         mov 	[year], cx
  2993 00003632 86F2                <1>         xchg 	dh,dl
  2994 00003634 668915[F2690000]    <1>         mov 	[month], dx
  2995                              <1> 	;
  2996 0000363B 66B93030            <1> 	mov 	cx, 3030h
  2997                              <1> 	;
  2998 0000363F A0[F4690000]        <1> 	mov 	al, [hour] ; Hour
  2999                              <1>         	; AL <= BCD number)
  3000 00003644 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3001                              <1> 					; AH = AL / 10h
  3002                              <1> 					; AL = AL MOD 10h
  3003 00003646 D50A                <1>         aad 	; AX= AH*10+AL
  3004 00003648 A2[F4690000]        <1> 	mov 	[hour], al
  3005 0000364D A0[F5690000]        <1> 	mov 	al, [hour+1] ; Minute
  3006                              <1>         	; AL <= BCD number)
  3007 00003652 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3008                              <1> 					; AH = AL / 10h
  3009                              <1> 					; AL = AL MOD 10h
  3010 00003654 D50A                <1>         aad 	; AX= AH*10+AL
  3011 00003656 A2[F5690000]        <1> 	mov 	[minute], al
  3012 0000365B A0[F6690000]        <1> 	mov 	al, [second] ; Second
  3013                              <1>         	; AL <= BCD number)
  3014 00003660 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3015                              <1> 					; AH = AL / 10h
  3016                              <1> 					; AL = AL MOD 10h
  3017 00003662 D50A                <1>         aad 	; AX= AH*10+AL
  3018 00003664 A2[F6690000]        <1> 	mov 	[second], al
  3019 00003669 66A1[F0690000]      <1> 	mov 	ax, [year] ; Year (century)
  3020                              <1>  	;push 	ax
  3021                              <1> 	; 08/01/2022
  3022 0000366F 50                  <1> 	push	eax
  3023                              <1> 	   	; AL <= BCD number)
  3024 00003670 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3025                              <1> 					; AH = AL / 10h
  3026                              <1> 					; AL = AL MOD 10h
  3027 00003672 D50A                <1>         aad 	; AX= AH*10+AL
  3028 00003674 B464                <1> 	mov 	ah, 100
  3029 00003676 F6E4                <1> 	mul 	ah
  3030 00003678 66A3[F0690000]      <1> 	mov 	[year], ax
  3031                              <1> 	;pop	ax
  3032                              <1> 	; 08/01/2022
  3033 0000367E 58                  <1> 	pop	eax
  3034 0000367F 88E0                <1> 	mov	al, ah
  3035                              <1>         	; AL <= BCD number)
  3036 00003681 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3037                              <1> 					; AH = AL / 10h
  3038                              <1> 					; AL = AL MOD 10h
  3039 00003683 D50A                <1>         aad 	; AX= AH*10+AL
  3040 00003685 660105[F0690000]    <1> 	add 	[year], ax
  3041 0000368C A0[F2690000]        <1> 	mov 	al, [month] ; Month
  3042                              <1>            	; AL <= BCD number)
  3043 00003691 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3044                              <1> 					; AH = AL / 10h
  3045                              <1> 					; AL = AL MOD 10h
  3046 00003693 D50A                <1>         aad 	; AX= AH*10+AL
  3047 00003695 A2[F2690000]        <1> 	mov 	[month], al	
  3048 0000369A A0[F3690000]        <1>         mov     al, [month+1]      	; Day
  3049                              <1>            	; AL <= BCD number)
  3050 0000369F D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3051                              <1> 					; AH = AL / 10h
  3052                              <1> 					; AL = AL MOD 10h
  3053 000036A1 D50A                <1>         aad 	; AX= AH*10+AL
  3054 000036A3 A2[F3690000]        <1>         mov     [day], al
  3055                              <1> 	
  3056                              <1> convert_to_epoch:
  3057                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3058                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3059                              <1> 	;
  3060                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3061                              <1> 	;
  3062                              <1> 	; Derived from DALLAS Semiconductor
  3063                              <1> 	; Application Note 31 (DS1602/DS1603)
  3064                              <1> 	; 6 May 1998
  3065 000036A8 29C0                <1> 	sub 	eax, eax
  3066 000036AA 66A1[F0690000]      <1> 	mov 	ax, [year]
  3067 000036B0 662DB207            <1> 	sub 	ax, 1970
  3068 000036B4 BA6D010000          <1> 	mov 	edx, 365
  3069 000036B9 F7E2                <1> 	mul 	edx
  3070 000036BB 31DB                <1> 	xor 	ebx, ebx
  3071 000036BD 8A1D[F2690000]      <1> 	mov 	bl, [month]
  3072 000036C3 FECB                <1> 	dec 	bl
  3073 000036C5 D0E3                <1> 	shl 	bl, 1
  3074                              <1> 	;sub	edx, edx
  3075 000036C7 668B93[F8690000]    <1> 	mov 	dx, [EBX+DMonth]
  3076 000036CE 8A1D[F3690000]      <1>         mov     bl, [day]
  3077 000036D4 FECB                <1> 	dec 	bl
  3078 000036D6 01D0                <1> 	add 	eax, edx
  3079 000036D8 01D8                <1> 	add 	eax, ebx
  3080                              <1> 			; EAX = days since 1/1/1970
  3081 000036DA 668B15[F0690000]    <1> 	mov 	dx, [year]
  3082 000036E1 6681EAB107          <1> 	sub 	dx, 1969
  3083 000036E6 66D1EA              <1> 	shr 	dx, 1
  3084 000036E9 66D1EA              <1> 	shr 	dx, 1		
  3085                              <1> 		; (year-1969)/4
  3086 000036EC 01D0                <1> 	add 	eax, edx
  3087                              <1> 			; + leap days since 1/1/1970
  3088 000036EE 803D[F2690000]02    <1> 	cmp 	byte [month], 2	; if past february
  3089 000036F5 7610                <1> 	jna 	short cte1
  3090 000036F7 668B15[F0690000]    <1> 	mov 	dx, [year]
  3091 000036FE 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3092 00003702 7503                <1> 	jnz 	short cte1		
  3093                              <1> 			; and if leap year
  3094 00003704 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3095                              <1> cte1: 			; compute seconds since 1/1/1970
  3096 00003707 BA18000000          <1> 	mov 	edx, 24
  3097 0000370C F7E2                <1> 	mul	edx
  3098 0000370E 8A15[F4690000]      <1> 	mov 	dl, [hour]
  3099 00003714 01D0                <1> 	add 	eax, edx
  3100                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3101                              <1> 	;mov	ebx, 60
  3102 00003716 B33C                <1> 	mov	bl, 60
  3103 00003718 F7E3                <1> 	mul	ebx
  3104 0000371A 8A15[F5690000]      <1> 	mov 	dl, [minute]
  3105 00003720 01D0                <1> 	add 	eax, edx
  3106                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3107                              <1> 	;mov 	ebx, 60
  3108 00003722 F7E3                <1> 	mul	ebx
  3109 00003724 8A15[F6690000]      <1> 	mov 	dl, [second]
  3110 0000372A 01D0                <1> 	add 	eax, edx
  3111                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3112 0000372C C3                  <1> 	retn
  3113                              <1> 
  3114                              <1> get_rtc_time:
  3115                              <1> 	; 15/03/2015
  3116                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3117                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3118                              <1> 	; INT 1Ah
  3119                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3120                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3121                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3122                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3123                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3124                              <1> 	;								
  3125                              <1> RTC_20: 				; GET RTC TIME
  3126 0000372D FA                  <1> 	cli
  3127 0000372E E80CD4FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3128 00003733 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3129                              <1> 
  3130 00003735 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3131 00003737 E8EDD3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3132 0000373C 88C6                <1> 	MOV	DH, AL			; SAVE
  3133 0000373E B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3134 00003740 E8E4D3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3135 00003745 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3136 00003747 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3137 00003749 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3138 0000374B E8D9D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3139 00003750 88C1                <1> 	MOV	CL, AL			; SAVE
  3140 00003752 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3141 00003754 E8D0D3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3142 00003759 88C5                <1> 	MOV	CH, AL			; SAVE
  3143 0000375B F8                  <1> 	CLC				; SET CY= 0
  3144                              <1> RTC_29:
  3145 0000375C FB                  <1> 	sti
  3146 0000375D C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3147                              <1> 
  3148                              <1> get_rtc_date:
  3149                              <1> 	; 15/03/2015
  3150                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3151                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3152                              <1> 	; INT 1Ah
  3153                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3154                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3155                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3156                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3157                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3158                              <1> 	;
  3159                              <1> RTC_40: 				; GET RTC DATE
  3160 0000375E FA                  <1> 	cli
  3161 0000375F E8DBD3FFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3162 00003764 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3163                              <1> 
  3164 00003766 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3165 00003768 E8BCD3FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3166 0000376D 88C2                <1> 	MOV	DL, AL			; SAVE
  3167 0000376F B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3168 00003771 E8B3D3FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3169 00003776 88C6                <1> 	MOV	DH, AL			; SAVE
  3170 00003778 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3171 0000377A E8AAD3FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3172 0000377F 88C1                <1> 	MOV	CL, AL			; SAVE
  3173 00003781 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3174 00003783 E8A1D3FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3175 00003788 88C5                <1> 	MOV	CH, AL			; SAVE
  3176 0000378A F8                  <1> 	CLC				; SET CY=0
  3177                              <1> RTC_49:
  3178 0000378B FB                  <1> 	sti
  3179 0000378C C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3180                              <1> 
  3181                              <1> set_date_time:
  3182                              <1> convert_from_epoch:
  3183                              <1> 	; 02/06/2022
  3184                              <1> 	; 01/06/2022 (BugFix)
  3185                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3186                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3187                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3188                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3189                              <1> 	;
  3190                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3191                              <1> 	;
  3192                              <1> 	; Derived from DALLAS Semiconductor
  3193                              <1> 	; Application Note 31 (DS1602/DS1603)
  3194                              <1> 	; 6 May 1998
  3195                              <1> 	;
  3196                              <1> 	; INPUT:
  3197                              <1> 	; EAX = Unix (Epoch) Time
  3198                              <1> 	;
  3199 0000378D 31D2                <1> 	xor 	edx, edx
  3200                              <1> 	; 02/06/2022
  3201 0000378F 31C9                <1> 	xor	ecx, ecx
  3202 00003791 31DB                <1> 	xor	ebx, ebx
  3203                              <1> 	;mov 	ecx, 60
  3204 00003793 B13C                <1> 	mov	cl, 60
  3205 00003795 F7F1                <1> 	div	ecx
  3206                              <1> 	;mov 	[imin], eax  ; whole minutes
  3207                              <1> 			     ; since 1/1/1970
  3208                              <1> 	;mov 	[second], dx ; leftover seconds
  3209 00003797 8815[F6690000]      <1> 	mov	[second], dl ; 02/06/2022
  3210 0000379D 29D2                <1> 	sub 	edx, edx
  3211 0000379F F7F1                <1> 	div	ecx
  3212                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3213                              <1> 	;		     ; since 1/1/1970
  3214                              <1> 	;mov 	[minute], dx ; leftover minutes
  3215 000037A1 8815[F5690000]      <1> 	mov	[minute], dl ; 02/06/2022
  3216 000037A7 31D2                <1> 	xor	edx, edx
  3217                              <1> 	;mov 	cx, 24
  3218 000037A9 B118                <1> 	mov 	cl, 24
  3219 000037AB F7F1                <1> 	div	ecx
  3220                              <1> 	;mov 	[iday], ax   ; whole days
  3221                              <1> 			     ; since 1/1/1970
  3222                              <1> 	;mov 	[hour], dx   ; leftover hours
  3223 000037AD 8815[F4690000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3224                              <1> 
  3225 000037B3 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3226                              <1> 			     ; 1/1/1968 	
  3227                              <1> 	;mov 	[iday], ax
  3228 000037B8 50                  <1> 	push 	eax
  3229 000037B9 29D2                <1> 	sub	edx, edx
  3230 000037BB B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3231 000037C0 F7F1                <1> 	div	ecx
  3232 000037C2 59                  <1> 	pop 	ecx
  3233                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3234                              <1> 	;push	dx
  3235                              <1> 	; 01/06/2022
  3236 000037C3 52                  <1> 	push 	edx
  3237                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3238 000037C4 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3239 000037C8 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3240 000037C9 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3241                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3242                              <1> 	;mov 	cx, [iday]
  3243 000037CC 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3244 000037CD 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3245 000037CF B96D010000          <1> 	mov 	ecx, 365
  3246 000037D4 31D2                <1> 	xor	edx, edx
  3247                              <1> 	; EAX = iday-lday, EDX = 0
  3248 000037D6 F7F1                <1> 	div	ecx
  3249                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3250                              <1> 	;jday = iday - (iyrs*365) - lday
  3251                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3252                              <1> 	;add	eax, 1968
  3253 000037D8 6605B007            <1> 	add 	ax, 1968     ; compute year
  3254 000037DC 66A3[F0690000]      <1> 	mov 	[year], ax
  3255                              <1> 	;mov 	cx, dx
  3256                              <1> 	; 02/06/2022
  3257 000037E2 89D1                <1> 	mov	ecx, edx
  3258                              <1> 	;mov 	dx, [qday]
  3259                              <1> 	;pop	dx
  3260                              <1> 	; 01/06/2022
  3261 000037E4 5A                  <1> 	pop 	edx
  3262 000037E5 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3263 000037EA 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3264 000037EC 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3265 000037F0 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3266 000037F1 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3267                              <1> cfe1:			
  3268                              <1> 	;mov 	[jday], cx
  3269                              <1> 	;mov 	bx, 12       ; estimate month
  3270                              <1> 	;sub	ebx, ebx
  3271                              <1> 	; 02/06/2022
  3272 000037F5 B30C                <1> 	mov	bl, 12
  3273 000037F7 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3274 000037FB 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3275                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3276                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3277                              <1> 	; 02/06/2022
  3278 000037FF 39D1                <1> 	cmp	ecx, edx 	 		
  3279 00003801 7319                <1> 	jnb 	short cfe3
  3280                              <1> 	;dec 	bx           ; month = month - 1
  3281 00003803 FECB                <1> 	dec	bl			
  3282                              <1> 	;shl 	bx, 1
  3283 00003805 D0E3                <1> 	shl	bl, 1
  3284 00003807 668B93[F8690000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3285                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3286                              <1> 	; 02/06/2022
  3287 0000380E D0EB                <1> 	shr	bl, 1
  3288 00003810 80FB01              <1> 	cmp	bl, 1
  3289                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3290 00003813 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3291 00003815 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3292 00003817 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3293                              <1> 	;inc 	dx           ; mday = mday + 1
  3294 00003819 42                  <1> 	inc	edx
  3295 0000381A EBE3                <1> 	jmp 	short cfe2
  3296                              <1> cfe3:
  3297                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3298                              <1> 	; 02/06/2022
  3299 0000381C FEC3                <1> 	inc	bl
  3300                              <1> 	;mov 	[month], bx
  3301 0000381E 881D[F2690000]      <1> 	mov	[month], bl
  3302                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1	
  3303 00003824 29D1                <1> 	sub	ecx, edx
  3304                              <1> 	;inc 	cx 			  
  3305 00003826 FEC1                <1> 	inc	cl
  3306                              <1> 	;mov 	[day], cx
  3307 00003828 880D[F3690000]      <1> 	mov	[day], cl    ; 02/06/2022
  3308                              <1> 	
  3309                              <1> 	; eax, ebx, ecx, edx is changed at return
  3310                              <1> 	; output ->
  3311                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3312                              <1> 
  3313                              <1> 	; 01/06/2022 (BugFix)	
  3314                              <1> _set_date:
  3315 0000382E 66A1[F0690000]      <1> 	mov	ax, [year]
  3316 00003834 B520                <1> 	mov	ch, 20h ; century (bcd)
  3317 00003836 662DD007            <1> 	sub	ax, 2000
  3318 0000383A 7306                <1> 	jnc	short set_date
  3319 0000383C B519                <1> 	mov	ch, 19h ; century (bcd) 
  3320 0000383E 6683C064            <1> 	add	ax, 100	
  3321                              <1> 	; 01/06/2022
  3322                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3323                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3324                              <1> set_date:
  3325                              <1>         ;mov	al, [year+1]
  3326                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3327                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3328                              <1> 	;		     ; AL = AH * 10h + AL
  3329                              <1> 	;mov 	ch, al ; century (BCD)
  3330                              <1> 	;mov 	al, [year]
  3331                              <1> 	; al = year (0-99) ; 01/06/2022
  3332 00003842 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3333 00003844 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3334                              <1> 			     ; AL = AH * 10h + AL
  3335 00003846 88C1                <1> 	mov 	cl, al ; year (BCD)
  3336 00003848 A0[F2690000]        <1>         mov 	al, [month]
  3337 0000384D D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3338 0000384F D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3339                              <1> 			     ; AL = AH * 10h + AL
  3340 00003851 88C6                <1> 	mov 	dh, al ; month (BCD)
  3341 00003853 A0[F3690000]        <1> 	mov 	al, [day]
  3342 00003858 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3343 0000385A D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3344                              <1> 			     ; AL = AH * 10h + AL
  3345                              <1> 	; 01/06/2022 (BugFix)
  3346 0000385C 88C2                <1> 	mov 	dl, al ; day (BCD)
  3347                              <1> 
  3348                              <1> 	; Set real-time clock date
  3349 0000385E E879000000          <1> 	call	set_rtc_date
  3350                              <1> set_time:
  3351                              <1>         ; Read real-time clock time 
  3352                              <1> 	; (get day light saving time bit status)
  3353 00003863 FA                  <1>  	cli
  3354 00003864 E8D6D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3355                              <1> 	; cf = 1 -> al = 0
  3356 00003869 7207                <1>         jc      short stime1
  3357 0000386B B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3358 0000386D E8B7D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3359                              <1> stime1:
  3360 00003872 FB                  <1> 	sti
  3361 00003873 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3362 00003875 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3363                              <1> 	; DL = 1 or 0 (day light saving time)
  3364                              <1> 	;	
  3365 00003877 A0[F4690000]        <1> 	mov 	al, [hour]
  3366 0000387C D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3367 0000387E D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3368                              <1> 			     ; AL = AH * 10h + AL
  3369 00003880 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3370 00003882 A0[F5690000]        <1>         mov     al, [minute]
  3371 00003887 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3372 00003889 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3373                              <1> 			     ; AL = AH * 10h + AL
  3374 0000388B 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3375 0000388D A0[F6690000]        <1>         mov     al, [second]
  3376 00003892 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3377 00003894 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3378                              <1> 			     ; AL = AH * 10h + AL
  3379 00003896 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3380                              <1> 
  3381                              <1> 	; Set real-time clock time
  3382                              <1>  	; call	set_rtc_time
  3383                              <1> set_rtc_time:
  3384                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3385                              <1> 	; 15/03/2015
  3386                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3387                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3388                              <1> 	; INT 1Ah
  3389                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3390                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3391                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3392                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3393                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3394                              <1> 	;								:
  3395                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3396                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3397                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3398                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3399                              <1> 	;
  3400                              <1> RTC_30: 				; SET RTC TIME
  3401 00003898 FA                  <1> 	cli
  3402 00003899 E8A1D2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3403 0000389E 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3404 000038A0 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3405                              <1> RTC_35:
  3406 000038A5 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3407 000038A7 B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3408 000038A9 E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3409 000038AE 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3410 000038B0 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3411 000038B2 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3412 000038B7 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3413 000038B9 B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3414 000038BB E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3415                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3416 000038C0 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3417 000038C4 E860D2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3418 000038C9 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3419 000038CB 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3420 000038CD 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3421 000038D0 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3422 000038D2 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3423 000038D4 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3424 000038D9 F8                  <1> 	CLC				; SET CY= 0
  3425 000038DA FB                  <1> 	sti
  3426 000038DB C3                  <1> 	RETn				; RETURN WITH CY= 0
  3427                              <1> 
  3428                              <1> set_rtc_date:
  3429                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3430                              <1> 	; 15/03/2015
  3431                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3432                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3433                              <1> 	; INT 1Ah
  3434                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3435                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3436                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3437                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3438                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3439                              <1> 	;
  3440                              <1> RTC_50: 				; SET RTC DATE
  3441 000038DC FA                  <1> 	cli
  3442 000038DD E85DD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3443 000038E2 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3444 000038E4 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3445                              <1> RTC_55:
  3446 000038E9 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3447 000038ED E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3448 000038F2 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3449 000038F4 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3450 000038F6 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3451 000038FB 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3452 000038FD B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3453 000038FF E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3454 00003904 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3455 00003906 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3456 00003908 E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3457 0000390D 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3458 0000390F B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3459 00003911 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3460                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3461 00003916 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3462 0000391A E80AD2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3463 0000391F 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3464 00003921 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3465 00003923 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3466 00003928 F8                  <1> 	CLC				; SET CY= 0
  3467 00003929 FB                  <1> 	sti
  3468 0000392A C3                  <1> 	RETn				; RETURN CY=0
  3469                              <1> 
  3470                              <1> 	; 15/03/2015
  3471                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3472 0000392B B426                <1> 	mov	ah, 26h
  3473 0000392D B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3474 0000392F E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3475 00003934 B482                <1> 	mov	ah, 82h
  3476 00003936 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3477 00003938 E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3478 0000393D B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3479 0000393F E8E5D1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3480 00003944 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3481                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3482                              <1> 	;RETn
  3483                              <1> 	; 12/01/2022
  3484 00003946 E9DED1FFFF          <1> 	jmp	CMOS_READ
  3485                              <1> 
  3486                              <1> 	; 15/03/2015
  3487                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3488                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3489 0000394B 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3490                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3491 0000394C D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3492 0000394E F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3493 0000394F D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3494 00003951 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3495 00003952 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3496 00003954 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3497 00003956 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3498 00003958 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3499 0000395A D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3500 0000395C E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3501 0000395E 90                  <1> 	nop			; I/O DELAY
  3502 0000395F E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3503                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3504 00003961 9D                  <1> 	popf	
  3505 00003962 C3                  <1> 	RETn
  3506                              <1> 
  3507                              <1> bf_init:
  3508                              <1> 	; 14/08/2015
  3509                              <1> 	; 02/07/2015
  3510                              <1> 	; 01/07/2015
  3511                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3512                              <1> 	; Buffer (pointer) initialization !
  3513                              <1> 	; 
  3514                              <1> 	; 17/07/2013 - 24/07/2013
  3515                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3516                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3517                              <1> 	;
  3518 00003963 BF[0C700000]        <1> 	mov	edi, bufp 
  3519 00003968 B8[047D0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3520 0000396D 29D2                <1> 	sub	edx, edx
  3521 0000396F FECA                <1> 	dec	dl
  3522 00003971 31C9                <1> 	xor	ecx, ecx
  3523 00003973 49                  <1> 	dec	ecx
  3524                              <1> bi0:
  3525 00003974 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3526 00003979 AB                  <1> 	stosd
  3527 0000397A 89C6                <1> 	mov	esi, eax
  3528 0000397C 8916                <1> 	mov	[esi], edx ; 000000FFh
  3529                              <1> 			   ; Not a valid device sign
  3530 0000397E 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3531                              <1> 		      ; Not a valid block number sign 	 	
  3532 00003981 3D[D4700000]        <1> 	cmp	eax, buffer
  3533 00003986 77EC                <1> 	ja	short bi0
  3534 00003988 B8[047D0000]        <1> 	mov	eax, sb0
  3535 0000398D AB                  <1> 	stosd
  3536 0000398E B8[0C7F0000]        <1> 	mov	eax, sb1
  3537 00003993 AB                  <1> 	stosd
  3538 00003994 89C6                <1> 	mov	esi, eax ; offset sb1
  3539 00003996 8916                <1> 	mov	[esi], edx ; 000000FFh
  3540                              <1> 			   ; Not a valid device sign
  3541 00003998 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3542                              <1> 		      ; Not a valid block number sign 	 
  3543                              <1> 	; 14/08/2015
  3544                              <1> 	;call 	rdev_init
  3545                              <1> 	;retn
  3546                              <1> 
  3547                              <1> rdev_init: ; root device, super block buffer initialization
  3548                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3549                              <1> 	; 14/08/2015
  3550                              <1> 	; Retro UNIX 386 v1 feature only !
  3551                              <1> 	;
  3552                              <1> 	; NOTE: Disk partitions (file systems), logical
  3553                              <1> 	; drive initialization, partition's start sector etc.
  3554                              <1> 	; will be coded here, later in 'ldrv_init'	
  3555                              <1> 
  3556 0000399B 0FB605[7A670000]    <1> 	movzx	eax, byte [boot_drv]
  3557                              <1> rdi_0:
  3558 000039A2 3C80                <1> 	cmp	al, 80h
  3559 000039A4 7202                <1> 	jb	short rdi_1
  3560 000039A6 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3561                              <1> rdi_1:
  3562 000039A8 A2[30700000]        <1> 	mov	[rdev], al
  3563 000039AD BB[047D0000]        <1>         mov	ebx, sb0 ; super block buffer
  3564 000039B2 8903                <1> 	mov 	[ebx], eax
  3565 000039B4 B001                <1> 	mov	al, 1 ; eax = 1
  3566 000039B6 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3567                              <1> 	;call 	diskio
  3568                              <1> 	;retn
  3569                              <1> 	; 24/12/2021
  3570 000039B9 E9C8250000          <1> 	jmp	diskio
  3571                              <1> 
  3572                              <1> ; 23/10/2015
  3573                              <1> com1_irq4:
  3574 000039BE [C6390000]          <1> 	dd	dummy_retn
  3575                              <1> com2_irq3:
  3576 000039C2 [C6390000]          <1> 	dd	dummy_retn
  3577                              <1> 
  3578                              <1> dummy_retn:
  3579 000039C6 C3                  <1> 	retn
  2102                                  %include 'u1.s'        ; 10/05/2015
  2103                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS1.INC
  2104                              <1> ; Last Modification: 27/02/2022
  2105                              <1> ; ----------------------------------------------------------------------------
  2106                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2107                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2108                              <1> ;
  2109                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2110                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2111                              <1> ; <Bell Laboratories (17/3/1972)>
  2112                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2113                              <1> ;
  2114                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2115                              <1> ;
  2116                              <1> ; ****************************************************************************
  2117                              <1> 
  2118                              <1> unkni: ; / used for all system calls
  2119                              <1> sysent: ; < enter to system call >
  2120                              <1> 	; 08/01/2022
  2121                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2122                              <1> 	; 19/10/2015
  2123                              <1> 	; 21/09/2015
  2124                              <1> 	; 01/07/2015
  2125                              <1> 	; 19/05/2015
  2126                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2127                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2128                              <1> 	;
  2129                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2130                              <1> 	; The trap type is determined and an indirect jump is made to 
  2131                              <1> 	; the appropriate system call handler. If there is a trap inside
  2132                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2133                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2134                              <1> 	; instructor is decoded to get the the system code part (see
  2135                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2136                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2137                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2138                              <1> 	; is called. If the call is legitimate control passes to the
  2139                              <1> 	; appropriate system routine.
  2140                              <1> 	;
  2141                              <1> 	; Calling sequence:
  2142                              <1> 	;	Through a trap caused by any sys call outside the system.
  2143                              <1> 	; Arguments:
  2144                              <1> 	;	Arguments of particular system call.	
  2145                              <1> 	; ...............................................................
  2146                              <1> 	;	
  2147                              <1> 	; Retro UNIX 8086 v1 modification: 
  2148                              <1> 	;       System call number is in EAX register.
  2149                              <1> 	;
  2150                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2151                              <1> 	;	registers depending of function details.
  2152                              <1>   	;
  2153                              <1> 	; 16/04/2015
  2154 000039C7 368925[44700000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2155                              <1> 	; save user registers
  2156 000039CE 1E                  <1> 	push	ds
  2157 000039CF 06                  <1> 	push	es
  2158 000039D0 0FA0                <1> 	push	fs
  2159 000039D2 0FA8                <1> 	push	gs
  2160 000039D4 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2161                              <1> 	;
  2162                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2163                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2164                              <1> 	;	for saving/restoring user registers.)
  2165                              <1> 	;
  2166 000039D5 50                  <1> 	push	eax ; 01/07/2015
  2167 000039D6 66B81000            <1> 	mov     ax, KDATA
  2168 000039DA 8ED8                <1>         mov     ds, ax
  2169 000039DC 8EC0                <1>         mov     es, ax
  2170 000039DE 8EE0                <1>         mov     fs, ax
  2171 000039E0 8EE8                <1>         mov     gs, ax
  2172 000039E2 A1[886C0000]        <1> 	mov	eax, [k_page_dir]
  2173 000039E7 0F22D8              <1> 	mov	cr3, eax
  2174 000039EA 58                  <1> 	pop	eax ; 01/07/2015
  2175                              <1> 	; 19/10/2015
  2176 000039EB FC                  <1> 	cld
  2177                              <1> 	;
  2178 000039EC FE05[41700000]      <1> 	inc	byte [sysflg]
  2179                              <1> 		; incb sysflg / indicate a system routine is in progress
  2180 000039F2 FB                  <1>         sti 	; 18/01/2014
  2181                              <1> 	;jnz	panic ; 24/05/2013
  2182                              <1> 	; 24/12/2021
  2183 000039F3 7405                <1> 	jz	short _1
  2184 000039F5 E984F9FFFF          <1> 	jmp	panic
  2185                              <1> 		; beq 1f
  2186                              <1> 		; jmp panic ; / called if trap inside system
  2187                              <1> ;1:
  2188                              <1> _1:	; 24/12/2021
  2189                              <1> 	; 16/04/2015
  2190 000039FA A3[4C700000]        <1> 	mov	[u.r0], eax
  2191 000039FF 8925[48700000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2192                              <1> 	;
  2193                              <1> 		; mov $s.syst+2,clockp
  2194                              <1> 		; mov r0,-(sp) / save user registers 
  2195                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2196                              <1> 			   ; / in u.r0
  2197                              <1> 		; mov r1,-(sp)
  2198                              <1> 		; mov r2,-(sp)
  2199                              <1> 		; mov r3,-(sp)
  2200                              <1> 		; mov r4,-(sp)
  2201                              <1> 		; mov r5,-(sp)
  2202                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2203                              <1> 		             ; / arithmetic unit
  2204                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2205                              <1> 		             ; / extended arithmetic unit
  2206                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2207                              <1> 		             ; / arithmetic unit
  2208                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2209                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2210                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2211                              <1> 		; sub $sys,r0 / get xxx code
  2212 00003A05 C1E002              <1> 	shl	eax, 2
  2213                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2214 00003A08 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2215                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2216                              <1> 	;jnb	short badsys
  2217                              <1> 		; bhis badsys / yes, bad system call
  2218                              <1> 	; 08/01/2022
  2219 00003A0D 7205                <1> 	jb	short _2
  2220 00003A0F E95D010000          <1> 	jmp	badsys
  2221                              <1> _2:
  2222                              <1> 	; 08/01/2022
  2223                              <1> 	;cmc
  2224                              <1> 	;pushf	
  2225                              <1> 	;push	eax
  2226 00003A14 8B2D[44700000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2227                              <1> 	;mov	al, 0FEh ; 11111110b
  2228                              <1> 	;;adc	al, 0 ; al = al + cf
  2229                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2230 00003A1A 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2231                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2232                              <1> 				 ; / and clear carry bit
  2233                              <1> 	;pop	ebp ; eax
  2234 00003A1E 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2235                              <1> 	;popf
  2236                              <1>         ;;jc	badsys
  2237                              <1> 	; 24/12/2021
  2238                              <1> 	;jnc	short _3  ; 08/01/2022
  2239                              <1> 	;jmp	badsys
  2240                              <1> ;_3:
  2241 00003A20 A1[4C700000]        <1> 	mov	eax, [u.r0]
  2242                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2243 00003A25 FFA5[2B3A0000]      <1> 	jmp	dword [ebp+syscalls]
  2244                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2245                              <1> 		            ; / to proper system routine.
  2246                              <1> syscalls: ; 1:
  2247                              <1> 	; 21/09/2015
  2248                              <1> 	; 01/07/2015
  2249                              <1> 	; 16/04/2015 (32 bit address modification) 
  2250 00003A2B [3B3B0000]          <1> 	dd sysrele	; / 0
  2251 00003A2F [E33B0000]          <1> 	dd sysexit 	; / 1
  2252 00003A33 [0E3D0000]          <1> 	dd sysfork 	; / 2
  2253 00003A37 [143E0000]          <1> 	dd sysread 	; / 3
  2254 00003A3B [273E0000]          <1> 	dd syswrite 	; / 4
  2255 00003A3F [903E0000]          <1> 	dd sysopen 	; / 5
  2256 00003A43 [BB3F0000]          <1> 	dd sysclose 	; / 6
  2257 00003A47 [893C0000]          <1> 	dd syswait 	; / 7
  2258 00003A4B [383F0000]          <1> 	dd syscreat 	; / 8
  2259 00003A4F [74430000]          <1> 	dd syslink 	; / 9
  2260 00003A53 [30440000]          <1> 	dd sysunlink 	; / 10
  2261 00003A57 [FA440000]          <1> 	dd sysexec 	; / 11
  2262 00003A5B [7D4B0000]          <1> 	dd syschdir 	; / 12
  2263 00003A5F [604C0000]          <1> 	dd systime 	; / 13
  2264 00003A63 [743F0000]          <1> 	dd sysmkdir 	; / 14
  2265 00003A67 [CD4B0000]          <1> 	dd syschmod 	; / 15
  2266 00003A6B [304C0000]          <1> 	dd syschown 	; / 16
  2267 00003A6F [934C0000]          <1> 	dd sysbreak 	; / 17
  2268 00003A73 [BA480000]          <1> 	dd sysstat 	; / 18
  2269 00003A77 [634D0000]          <1> 	dd sysseek 	; / 19
  2270 00003A7B [754D0000]          <1> 	dd systell 	; / 20
  2271 00003A7F [A9580000]          <1> 	dd sysmount 	; / 21
  2272 00003A83 [94590000]          <1> 	dd sysumount 	; / 22
  2273 00003A87 [F14D0000]          <1> 	dd syssetuid 	; / 23
  2274 00003A8B [224E0000]          <1> 	dd sysgetuid 	; / 24
  2275 00003A8F [6F4C0000]          <1> 	dd sysstime 	; / 25
  2276 00003A93 [E54D0000]          <1> 	dd sysquit 	; / 26
  2277 00003A97 [D94D0000]          <1> 	dd sysintr 	; / 27
  2278 00003A9B [97480000]          <1> 	dd sysfstat 	; / 28
  2279 00003A9F [D83F0000]          <1> 	dd sysemt 	; / 29
  2280 00003AA3 [24400000]          <1> 	dd sysmdate 	; / 30
  2281 00003AA7 [7E400000]          <1> 	dd sysstty 	; / 31
  2282 00003AAB [67420000]          <1> 	dd sysgtty 	; / 32
  2283 00003AAF [1F400000]          <1> 	dd sysilgins 	; / 33
  2284 00003AB3 [3F620000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2285                              <1> 			     ; 11/06/2014
  2286 00003AB7 [56620000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2287                              <1> 			     ; 01/07/2015
  2288 00003ABB [2E630000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2289                              <1> 			     ; 21/09/2015 - get last error number
  2290                              <1> end_of_syscalls:
  2291                              <1> 
  2292                              <1> error:
  2293                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2294                              <1> 	; 17/09/2015
  2295                              <1> 	; 03/09/2015
  2296                              <1> 	; 01/09/2015
  2297                              <1> 	; 09/06/2015
  2298                              <1> 	; 13/05/2015
  2299                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2300                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2301                              <1> 	;
  2302                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2303                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2304                              <1> 	;
  2305                              <1> 	; INPUTS -> none
  2306                              <1> 	; OUTPUTS ->
  2307                              <1> 	;	processor status - carry (c) bit is set (means error)
  2308                              <1> 	;
  2309                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2310                              <1> 	; 	      Because, jumps to error procedure
  2311                              <1> 	;	      disrupts push-pop nesting balance)
  2312                              <1> 	;
  2313 00003ABF 8B2D[44700000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2314 00003AC5 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2315                              <1> 				 ; (system call will return with cf = 1)
  2316                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2317                              <1> 		               ; / users stack
  2318                              <1> 	; 17/09/2015
  2319 00003AC9 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2320                              <1> 				 ; for saving/restoring user registers	
  2321                              <1> 	;cmp	ebp, [u.usp]
  2322                              <1> 	;je	short err0	
  2323 00003ACC 892D[48700000]      <1> 	mov	[u.usp], ebp
  2324                              <1> ;err0:
  2325                              <1> 	; 01/09/2015
  2326 00003AD2 8B25[48700000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2327                              <1> 				    ; 10/04/2013
  2328                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2329                              <1> 				    ; related procedures will jump to 'error'
  2330                              <1> 				    ; procedure directly without returning to 
  2331                              <1> 				    ; the caller procedure. So, stack pointer
  2332                              <1>                                     ; must be restored here.)
  2333                              <1> 	; 13/05/2015
  2334                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2335                              <1> 	;	'get last error' system call later. 	
  2336                              <1> 
  2337                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2338 00003AD8 C605[B3700000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2339                              <1> 
  2340                              <1> sysret: ; < return from system call>
  2341                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2342                              <1> 	; 10/09/2015
  2343                              <1> 	; 29/07/2015
  2344                              <1> 	; 25/06/2015
  2345                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2346                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2347                              <1> 	;
  2348                              <1> 	; 'sysret' first checks to see if process is about to be 
  2349                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2350                              <1> 	; If not, following happens:	 
  2351                              <1> 	; 	1) The user's stack pointer is restored.
  2352                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2353                              <1> 	;	   i-node has been modified. If it has, it is written out
  2354                              <1> 	;	   via 'ppoke'.
  2355                              <1> 	;	3) If the super block has been modified, it is written out
  2356                              <1> 	;	   via 'ppoke'.				
  2357                              <1> 	;	4) If the dismountable file system's super block has been
  2358                              <1> 	;	   modified, it is written out to the specified device
  2359                              <1> 	;	   via 'ppoke'.
  2360                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2361                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2362                              <1> 	;	   another user a chance to run.
  2363                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2364                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2365                              <1> 	;
  2366                              <1> 	; Calling sequence:
  2367                              <1> 	;	jump table or 'br sysret'
  2368                              <1> 	; Arguments: 
  2369                              <1> 	;	-	
  2370                              <1> 	; ...............................................................
  2371                              <1> 	;	
  2372                              <1> 	; ((AX=r1 for 'iget' input))
  2373                              <1> 	;	
  2374                              <1> 	;xor	ax, ax ; 04/05/2013
  2375                              <1> 	; 24/12/2021
  2376 00003ADF 31C0                <1> 	xor	eax, eax
  2377                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2378 00003AE1 FEC0                <1> 	inc	al ; 04/05/2013
  2379 00003AE3 3805[9A700000]      <1> 	cmp	[u.bsys], al ; 1
  2380                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2381                              <1> 	;jnb	sysexit ; 04/05/2013
  2382                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2383                              <1> 	; 24/12/2021
  2384 00003AE9 720F                <1> 	jb	short _3
  2385 00003AEB C705[A1700000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2385 00003AF3 0000                <1>
  2386 00003AF5 E9E9000000          <1> 	jmp	sysexit
  2387                              <1> _3:
  2388                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2389                              <1> 		; mov u.sp,sp / no point stack to users stack
  2390 00003AFA FEC8                <1> 	dec 	al ; mov ax, 0
  2391                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2392 00003AFC E8DB160000          <1> 	call	iget
  2393                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2394                              <1> 		            ; / it is written out
  2395                              <1> 	;xor 	ax, ax ; 0
  2396                              <1> 	; 24/12/2021
  2397 00003B01 31C0                <1> 	xor	eax, eax
  2398 00003B03 3805[3F700000]      <1> 	cmp	[smod], al ; 0
  2399                              <1> 		; tstb	smod / has the super block been modified
  2400 00003B09 7614                <1> 	jna	short sysret1
  2401                              <1> 		; beq	1f / no, 1f
  2402 00003B0B A2[3F700000]        <1> 	mov	[smod], al ; 0
  2403                              <1> 		; clrb smod / yes, clear smod
  2404 00003B10 BB[047D0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2405 00003B15 66810B0002          <1>    	or	word [ebx], 200h ;;
  2406                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2407                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2408                              <1> 		      	      ; / output
  2409                              <1> 	; AX = 0
  2410 00003B1A E84F230000          <1> 	call 	poke ; 07/08/2013
  2411                              <1> 	; call	ppoke
  2412                              <1> 	; AX = 0
  2413                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2414                              <1> sysret1: ;1:
  2415 00003B1F 3805[40700000]      <1> 	cmp	[mmod], al ; 0
  2416                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2417                              <1> 		           ; / system
  2418 00003B25 7614                <1> 	jna	short sysrel0
  2419                              <1> 		; beq 1f / been modified?  no, 1f
  2420 00003B27 A2[40700000]        <1> 	mov	[mmod], al ; 0	
  2421                              <1> 		; clrb	mmod / yes, clear mmod
  2422                              <1>         ;mov    ax, [mntd]
  2423                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2424 00003B2C BB[0C7F0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2425                              <1>         ;;mov	[ebx], al
  2426                              <1> 	;mov    [sb1], al
  2427                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2428 00003B31 66810B0002          <1> 	or	word [ebx], 200h
  2429                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2430                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2431 00003B36 E833230000          <1> 	call	poke ; 07/08/2013
  2432                              <1> 	;call	ppoke 
  2433                              <1> 		; jsr r0,ppoke / write it out to its device
  2434                              <1>         ;xor    al, al ; 26/04/2013       
  2435                              <1> ;1:
  2436                              <1> 		; tstb uquant / is the time quantum 0?
  2437                              <1> 		; bne 1f / no, don't swap it out
  2438                              <1> 
  2439                              <1> sysrele: ; < release >
  2440                              <1> 	; 14/10/2015
  2441                              <1> 	; 01/09/2015
  2442                              <1> 	; 24/07/2015
  2443                              <1> 	; 14/05/2015
  2444                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2445                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2446                              <1> 	;
  2447                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2448                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2449                              <1> 	; turns off the system flag. It then checked to see if there is
  2450                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2451                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2452                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2453                              <1> 	; the user, a rti is made.
  2454                              <1> 	;
  2455                              <1> 	; Calling sequence:
  2456                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2457                              <1> 	; Arguments:
  2458                              <1> 	;	-	
  2459                              <1> 	; ...............................................................
  2460                              <1> 	;	
  2461                              <1> 	; 23/02/2014 (swapret)
  2462                              <1> 	; 22/09/2013
  2463                              <1> sysrel0: ;1:
  2464 00003B3B 803D[8E700000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2465                              <1> 		; tstb uquant / is the time quantum 0?
  2466 00003B42 7705                <1>         ja      short swapret
  2467                              <1> 		; bne 1f / no, don't swap it out
  2468                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2469 00003B44 E829130000          <1> 	call	tswap
  2470                              <1> 		; jsr r0,tswap / yes, swap it out
  2471                              <1> ;
  2472                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2473                              <1> swapret: ;1:
  2474                              <1> 	; 10/09/2015
  2475                              <1> 	; 01/09/2015
  2476                              <1> 	; 14/05/2015
  2477                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2478                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2479                              <1> 	; cli
  2480                              <1> 	; 24/07/2015
  2481                              <1> 	;
  2482                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2483                              <1> 	;; mov	esp, [u.usp]
  2484                              <1> 
  2485                              <1> 	; 22/09/2013
  2486 00003B49 E8FB140000          <1> 	call	isintr
  2487                              <1> 	; 20/10/2013
  2488 00003B4E 7405                <1> 	jz	short sysrel1
  2489 00003B50 E877000000          <1> 	call	intract
  2490                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2491                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2492                              <1> 		               ; / action
  2493                              <1> sysrel1:
  2494 00003B55 FA                  <1> 	cli ; 14/10/2015
  2495 00003B56 FE0D[41700000]      <1> 	dec	byte [sysflg]
  2496                              <1> 		; decb sysflg / turn system flag off
  2497 00003B5C A1[A5700000]        <1> 	mov     eax, [u.pgdir]
  2498 00003B61 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2499                              <1> 			  ; (others are different than kernel page tables) 
  2500                              <1> 	; 10/09/2015
  2501 00003B64 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2502                              <1> 		; mov (sp)+,sc / restore user registers
  2503                              <1> 		; mov (sp)+,mq
  2504                              <1> 		; mov (sp)+,ac
  2505                              <1> 		; mov (sp)+,r5
  2506                              <1> 		; mov (sp)+,r4
  2507                              <1> 		; mov (sp)+,r3
  2508                              <1> 		; mov (sp)+,r2
  2509                              <1> 	;
  2510 00003B65 A1[4C700000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2511 00003B6A 0FA9                <1> 	pop	gs
  2512 00003B6C 0FA1                <1> 	pop	fs
  2513 00003B6E 07                  <1> 	pop	es
  2514 00003B6F 1F                  <1> 	pop	ds
  2515 00003B70 CF                  <1> 	iretd	
  2516                              <1> 		; rti / no, return from interrupt
  2517                              <1> 
  2518                              <1> badsys:
  2519                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2520                              <1> 	; (Major Modification: 'core' dumping procedure in
  2521                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2522                              <1> 	;	has been changed to print 'Invalid System Call !'
  2523                              <1> 	;	message on the user's console tty.)
  2524                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2525                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2526                              <1> 	; (EAX = Function number)  
  2527                              <1> 	;
  2528 00003B71 FE05[9A700000]      <1> 	inc	byte [u.bsys]
  2529                              <1> 	;
  2530 00003B77 8B1D[44700000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2531 00003B7D 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2532 00003B7F E86BDBFFFF          <1> 	call	dwordtohex
  2533 00003B84 8915[E4690000]      <1> 	mov	[bsys_msg_eip], edx
  2534 00003B8A A3[E8690000]        <1> 	mov	[bsys_msg_eip+4], eax
  2535 00003B8F A1[4C700000]        <1> 	mov	eax, [u.r0]
  2536 00003B94 E856DBFFFF          <1> 	call	dwordtohex
  2537 00003B99 8915[D4690000]      <1> 	mov	[bsys_msg_eax], edx
  2538 00003B9F A3[D8690000]        <1> 	mov	[bsys_msg_eax+4], eax
  2539                              <1> 	; 24/12/2021
  2540                              <1> 	;xor	eax, eax
  2541                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2542                              <1> 	;mov	ebx, [u.fofp]
  2543                              <1> 	;mov	[ebx], eax
  2544                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2545                              <1> 	;inc	eax
  2546                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2547                              <1> 		; writei
  2548                              <1> 		; INPUTS ->
  2549                              <1> 		;    r1 - inode number
  2550                              <1> 		;    u.count - byte count to be written
  2551                              <1> 		;    u.base - points to user buffer
  2552                              <1> 		;    u.fofp - points to word with current file offset
  2553                              <1> 		; OUTPUTS ->
  2554                              <1> 		;    u.count - cleared
  2555                              <1> 		;    u.nread - accumulates total bytes passed back	
  2556                              <1> 		;
  2557                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2558                              <1> 	;call	writei
  2559                              <1> 	;;mov	eax, 1
  2560                              <1> 	;jmp	sysexit
  2561                              <1> 
  2562                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2563 00003BA4 BE[B5690000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2564 00003BA9 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2565 00003BB0 8A83[A76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2566 00003BB6 C605[B76C0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2567 00003BBD A2[A0700000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2568 00003BC2 E84C270000          <1> 	call	print_cmsg
  2569                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2570 00003BC7 E9F3FEFFFF          <1> 	jmp	error
  2571                              <1> 
  2572                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2573                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2574                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2575                              <1> 		; br 1f / error
  2576                              <1> 		; neg r1 / negate the i-number to open the core image file
  2577                              <1> 		       ; / for writing
  2578                              <1> 		; jsr r0,iopen / open the core image file
  2579                              <1> 		; jsr r0,itrunc / free all associated blocks
  2580                              <1> 		; br 2f
  2581                              <1> ;1:
  2582                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2583                              <1> 		; jsr r0,maknod / make an i-node
  2584                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2585                              <1> ;2:
  2586                              <1> 		; mov $core,u.base / move address core to u.base
  2587                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2588                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2589                              <1> 		; clr u.off / clear user offset
  2590                              <1> 		; jsr r0,writei / write out the core image to the user
  2591                              <1> 		; mov $user,u.base / pt. u.base to user
  2592                              <1> 		; mov $64.,u.count / u.count = 64
  2593                              <1> 		; jsr r0,writei / write out all the user parameters
  2594                              <1> 		; neg r1 / make i-number positive
  2595                              <1> 		; jsr r0,iclose / close the core image file
  2596                              <1> 		; br sysexit /
  2597                              <1> ;3:
  2598                              <1> 		; <core\0\0>
  2599                              <1> 
  2600                              <1> intract: ; / interrupt action
  2601                              <1> 	; 14/10/2015
  2602                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2603                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2604                              <1> 	;
  2605                              <1> 	; Retro UNIX 8086 v1 modification !
  2606                              <1> 	; (Process/task switching and quit routine by using
  2607                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2608                              <1> 	;
  2609                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2610                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2611                              <1> 	;		'intract' will jump to 'sysexit'.
  2612                              <1> 	;	    Intract will return to the caller 
  2613                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2614                              <1> 	; 14/10/2015
  2615 00003BCC FB                  <1> 	sti
  2616                              <1> 	; 07/12/2013	
  2617 00003BCD 66FF05[92700000]    <1> 	inc 	word [u.quit]
  2618 00003BD4 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2619 00003BD6 66FF0D[92700000]    <1> 	dec	word [u.quit]
  2620                              <1> 	; 16/04/2015
  2621 00003BDD C3                  <1> 	retn
  2622                              <1> intrct0:	
  2623 00003BDE 58                  <1> 	pop	eax ; call intract -> retn
  2624                              <1> 	;
  2625 00003BDF 31C0                <1> 	xor 	eax, eax
  2626 00003BE1 FEC0                <1> 	inc	al  ; mov ax, 1
  2627                              <1> ;;;
  2628                              <1> 	; UNIX v1 original 'intract' routine... 
  2629                              <1> 	; / interrupt action
  2630                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2631                              <1> 		; bne 1f / no, 1f
  2632                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2633                              <1> 	; 1: / now in user area
  2634                              <1> 		; mov r1,-(sp) / save r1
  2635                              <1> 		; mov u.ttyp,r1 
  2636                              <1> 			; / pointer to tty buffer in control-to r1
  2637                              <1> 		; cmpb 6(r1),$177
  2638                              <1> 			; / is the interrupt char equal to "del"
  2639                              <1> 		; beq 1f / yes, 1f
  2640                              <1> 		; clrb 6(r1) 
  2641                              <1> 		        ; / no, clear the byte 
  2642                              <1> 			; / (must be a quit character)
  2643                              <1> 		; mov (sp)+,r1 / restore r1
  2644                              <1> 		; clr u.quit / clear quit flag
  2645                              <1> 		; bis $20,2(sp) 
  2646                              <1> 		    	; / set trace for quit (sets t bit of 
  2647                              <1> 			; / ps-trace trap)
  2648                              <1> 		; rti   ;  / return from interrupt
  2649                              <1> 	; 1: / interrupt char = del
  2650                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2651                              <1> 			   ; / in the buffer
  2652                              <1> 		; mov (sp)+,r1 / restore r1
  2653                              <1> 		; cmp u.intr,$core / should control be 
  2654                              <1> 				; / transferred to loc core?
  2655                              <1> 		; blo 1f
  2656                              <1> 		; jmp *u.intr / user to do rti yes, 
  2657                              <1> 				; / transfer to loc core
  2658                              <1> 	; 1:
  2659                              <1> 		; sys 1 / exit
  2660                              <1> 
  2661                              <1> sysexit: ; <terminate process>
  2662                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2663                              <1> 	; 01/09/2015
  2664                              <1> 	; 31/08/2015
  2665                              <1> 	; 14/05/2015
  2666                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2667                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2668                              <1> 	;
  2669                              <1> 	; 'sysexit' terminates a process. First each file that
  2670                              <1> 	; the process has opened is closed by 'flose'. The process
  2671                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2672                              <1> 	; searched to find children of the dying process. If any of
  2673                              <1> 	; children are zombies (died by not waited for), they are
  2674                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2675                              <1> 	; dying process's parent. When the parent is found, it is
  2676                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2677                              <1> 	; one of these, the dying process just dies. If it is waiting
  2678                              <1> 	; for a child process to die, it notified that it doesn't 
  2679                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2680                              <1> 	; (waiting to active). It is awakened and put on runq by
  2681                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2682                              <1> 	; it will never be run again but stays around until a 'wait'
  2683                              <1> 	; is completed by it's parent process. If the parent is not
  2684                              <1> 	; found, process just dies. This means 'swap' is called with
  2685                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2686                              <1> 	; to write out the process and 'rswap' reads the new process
  2687                              <1> 	; over the one that dies..i.e., the dying process is 
  2688                              <1> 	; overwritten and destroyed.	
  2689                              <1>  	;
  2690                              <1> 	; Calling sequence:
  2691                              <1> 	;	sysexit or conditional branch.
  2692                              <1> 	; Arguments:
  2693                              <1> 	;	-	
  2694                              <1> 	; ...............................................................
  2695                              <1> 	;	
  2696                              <1> 	; Retro UNIX 8086 v1 modification: 
  2697                              <1> 	;       System call number (=1) is in EAX register.
  2698                              <1> 	;
  2699                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2700                              <1> 	;       registers depending of function details.
  2701                              <1> 	;
  2702                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2703                              <1> 	;
  2704                              <1> ; / terminate process
  2705                              <1> 	; AX = 1
  2706                              <1> 	;dec 	ax ; 0
  2707                              <1> 	; 24/12/2021
  2708 00003BE3 48                  <1> 	dec	eax ; 0
  2709                              <1> 	;dec 	ax ; 0
  2710 00003BE4 66A3[90700000]      <1> 	mov	[u.intr], ax ; 0
  2711                              <1> 		; clr u.intr / clear interrupt control word
  2712                              <1> 		; clr r1 / clear r1
  2713                              <1> 	; AX = 0
  2714                              <1> sysexit_1: ; 1:
  2715                              <1> 	; AX = File descriptor
  2716                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2717                              <1> 		; / Search the whole list
  2718 00003BEA E8690D0000          <1> 	call	fclose
  2719                              <1> 		; jsr r0,fclose / close all files the process opened
  2720                              <1> 	;; ignore error return
  2721                              <1> 		; br .+2 / ignore error return
  2722                              <1> 	;inc	ax
  2723 00003BEF FEC0                <1> 	inc	al
  2724                              <1> 		; inc r1 / increment file descriptor
  2725                              <1> 	;cmp	ax, 10
  2726 00003BF1 3C0A                <1> 	cmp	al, 10
  2727                              <1> 		; cmp r1,$10. / end of u.fp list?
  2728 00003BF3 72F5                <1> 	jb	short sysexit_1
  2729                              <1> 		; blt 1b / no, go back
  2730 00003BF5 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2731                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2732 00003BFC 88A3[C76D0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2733                              <1> 		; clrb p.stat-1(r1) / free the process
  2734                              <1> 	;shl	bx, 1
  2735 00003C02 D0E3                <1> 	shl	bl, 1
  2736                              <1> 		; asl r1 / use r1 for index into the below tables
  2737 00003C04 668B8B[666D0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2738                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2739 00003C0B 668B93[866D0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2740                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2741                              <1> 	; xor 	bx, bx ; 0
  2742 00003C12 30DB                <1> 	xor	bl, bl ; 0
  2743                              <1> 		; clr r2
  2744 00003C14 31F6                <1> 	xor	esi, esi ; 0
  2745                              <1> 		; clr r5 / initialize reg
  2746                              <1> sysexit_2: ; 1:
  2747                              <1> 	        ; / find children of this dying process, 
  2748                              <1> 		; / if they are zombies, free them
  2749                              <1> 	;add	bx, 2
  2750 00003C16 80C302              <1> 	add	bl, 2
  2751                              <1> 		; add $2,r2 / search parent process table 
  2752                              <1> 		          ; / for dying process's name
  2753 00003C19 66398B[866D0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2754                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2755 00003C20 7513                <1> 	jne	short sysexit_4
  2756                              <1> 		; bne 3f / no
  2757                              <1> 	;shr	bx, 1
  2758 00003C22 D0EB                <1> 	shr	bl, 1
  2759                              <1> 		; asr r2 / yes, it is a parent
  2760 00003C24 80BB[C76D0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2761                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2762                              <1> 				     ; / dying process a zombie
  2763 00003C2B 7506                <1> 	jne	short sysexit_3 
  2764                              <1> 		; bne 2f / no
  2765 00003C2D 88A3[C76D0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2766                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2767                              <1> sysexit_3: ; 2:
  2768                              <1> 	;shr	bx, 1
  2769 00003C33 D0E3                <1> 	shl	bl, 1
  2770                              <1> 		; asl r2
  2771                              <1> sysexit_4: ; 3:
  2772                              <1> 		; / search the process name table 
  2773                              <1> 		; / for the dying process's parent
  2774 00003C35 663993[666D0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2775                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2776 00003C3C 7502                <1> 	jne	short sysexit_5
  2777                              <1> 		; bne 3f / no
  2778 00003C3E 89DE                <1> 	mov	esi, ebx
  2779                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2780                              <1> 		          ; / process # x2) in r5
  2781                              <1> sysexit_5: ; 3:
  2782                              <1> 	;cmp	bx, nproc + nproc
  2783 00003C40 80FB20              <1> 	cmp	bl, nproc + nproc
  2784                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2785 00003C43 72D1                <1> 	jb	short sysexit_2
  2786                              <1> 		; blt 1b / no, go back
  2787                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2788 00003C45 21F6                <1> 	and	esi, esi ; r5=r1
  2789 00003C47 7431                <1> 	jz	short sysexit_6
  2790                              <1> 		; beq 2f / no parent has been found. 
  2791                              <1> 		       ; / The process just dies
  2792 00003C49 66D1EE              <1> 	shr	si, 1
  2793                              <1> 		; asr r1 / set up index to p.stat
  2794 00003C4C 8A86[C76D0000]      <1> 	mov	al, [esi+p.stat-1]
  2795                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2796 00003C52 20C0                <1> 	and	al, al
  2797 00003C54 7424                <1> 	jz	short sysexit_6
  2798                              <1> 		; beq 2f / if its been freed, 2f
  2799 00003C56 3C03                <1> 	cmp	al, 3
  2800                              <1> 		; cmp r2,$3 / is parent a zombie?
  2801 00003C58 7420                <1> 	je	short sysexit_6
  2802                              <1> 		; beq 2f / yes, 2f
  2803                              <1> 	; BH = 0
  2804 00003C5A 8A1D[9B700000]      <1> 	mov	bl, [u.uno]
  2805                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2806 00003C60 C683[C76D0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2807                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2808                              <1> 	; 05/02/2014
  2809 00003C67 3C01                <1> 	cmp	al, 1 ; SRUN
  2810 00003C69 740F                <1> 	je	short sysexit_6
  2811                              <1> 	;cmp	al, 2
  2812                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2813                              <1> 			  ; / this child to die
  2814                              <1> 	;jne	short sysexit_6	
  2815                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2816                              <1> 	; 05/02/2014
  2817                              <1> 	; p.stat = 2 --> waiting
  2818                              <1> 	; p.stat = 4 --> sleeping
  2819 00003C6B C686[C76D0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2820                              <1> 	;dec	byte [esi+p.stat-1]
  2821                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2822 00003C72 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2823                              <1> 	; 
  2824                              <1> 	;mov	ebx, runq + 4
  2825                              <1> 		; mov $runq+4,r2 / on the runq
  2826 00003C75 E8CF120000          <1> 	call	putlu
  2827                              <1> 		; jsr r0, putlu
  2828                              <1> sysexit_6: ; 2:
  2829                              <1> 	; 31/08/2015
  2830                              <1> 		; / the process dies
  2831 00003C7A C605[9B700000]00    <1> 	mov	byte [u.uno], 0
  2832                              <1> 		; clrb u.uno / put zero as the process number, 
  2833                              <1> 	           ; / so "swap" will
  2834 00003C81 E8F6110000          <1> 	call	swap
  2835                              <1> 		; jsr r0,swap / overwrite process with another process
  2836                              <1> hlt_sys:
  2837                              <1> 	;sti ; 18/01/2014
  2838                              <1> hlts0:
  2839 00003C86 F4                  <1> 	hlt
  2840 00003C87 EBFD                <1> 	jmp	short hlts0
  2841                              <1> 		; 0 / and thereby kill it; halt?
  2842                              <1> 
  2843                              <1> 
  2844                              <1> syswait: ; < wait for a processs to die >
  2845                              <1> 	; 09/02/2022
  2846                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2847                              <1> 	; 17/09/2015
  2848                              <1> 	; 02/09/2015
  2849                              <1> 	; 01/09/2015
  2850                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2851                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2852                              <1> 	;
  2853                              <1> 	; 'syswait' waits for a process die. 
  2854                              <1> 	; It works in following way:
  2855                              <1> 	;    1) From the parent process number, the parent's 
  2856                              <1> 	; 	process name is found. The p.ppid table of parent
  2857                              <1> 	;	names is then searched for this process name.
  2858                              <1> 	;	If a match occurs, r2 contains child's process
  2859                              <1> 	;	number. The child status is checked to see if it is
  2860                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2861                              <1> 	;	If it is, the child process is freed and it's name
  2862                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2863                              <1> 	;	If the child is not a zombie, nothing happens and
  2864                              <1> 	;	the search goes on through the p.ppid table until
  2865                              <1> 	;	all processes are checked or a zombie is found.
  2866                              <1> 	;    2) If no zombies are found, a check is made to see if
  2867                              <1> 	;	there are any children at all. If there are none,
  2868                              <1> 	;	an error return is made. If there are, the parent's
  2869                              <1> 	;	status is set to 2 (waiting for child to die),
  2870                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2871                              <1> 	;	is made to wait on the next process.
  2872                              <1> 	;
  2873                              <1> 	; Calling sequence:
  2874                              <1> 	;	?
  2875                              <1> 	; Arguments:
  2876                              <1> 	;	-
  2877                              <1> 	; Inputs: - 
  2878                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2879                              <1> 	; ...............................................................
  2880                              <1> 	;				
  2881                              <1> 	
  2882                              <1> ; / wait for a process to die
  2883                              <1> 
  2884                              <1> syswait_0:
  2885 00003C89 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2886                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2887 00003C90 D0E3                <1> 	shl	bl, 1
  2888                              <1> 	;shl	bx, 1
  2889                              <1> 		; asl r1 / x2 to get index into p.pid table
  2890 00003C92 668B83[666D0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2891                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2892 00003C99 31F6                <1> 	xor	esi, esi
  2893                              <1> 		; clr r2
  2894 00003C9B 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2895                              <1> 	;xor 	cl, cl
  2896                              <1> 		; clr r3 / initialize reg 3
  2897                              <1> syswait_1: ; 1:
  2898                              <1> 	; 09/02/2022
  2899 00003C9D 46                  <1> 	inc	esi
  2900 00003C9E 46                  <1> 	inc	esi
  2901                              <1> 	;add	si, 2
  2902                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2903                              <1> 			  ; / search table of parent processes 
  2904                              <1> 			  ; / for this process name
  2905 00003C9F 663B86[866D0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2906                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2907                              <1> 			            ; / process number
  2908 00003CA6 7531                <1> 	jne	short syswait_3
  2909                              <1> 		;bne 3f / branch if no match of parent process name
  2910                              <1> 	;inc	cx
  2911 00003CA8 FEC1                <1> 	inc	cl
  2912                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2913                              <1> 	; 09/02/2022
  2914 00003CAA D1EE                <1> 	shr	esi, 1
  2915                              <1> 	;shr	si, 1
  2916                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2917                              <1> 	; The possible states ('p.stat' values) of a process are:
  2918                              <1> 	;	0 = free or unused
  2919                              <1> 	;	1 = active
  2920                              <1> 	;	2 = waiting for a child process to die
  2921                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2922 00003CAC 80BE[C76D0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2923                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2924 00003CB3 7522                <1> 	jne	short syswait_2
  2925                              <1> 		; bne 2f / no, skip it
  2926 00003CB5 88BE[C76D0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2927                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2928                              <1> 	; 09/02/2022
  2929 00003CBB D1E6                <1> 	shl	esi, 1
  2930                              <1> 	;shl	si, 1
  2931                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2932 00003CBD 0FB786[666D0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2933 00003CC4 A3[4C700000]        <1> 	mov	[u.r0], eax
  2934                              <1> 		; mov p.pid-2(r2),*u.r0 
  2935                              <1> 			      ; / put childs process name in (u.r0)
  2936                              <1> 	;
  2937                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2938                              <1> 	;
  2939                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2940                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2941                              <1> 	; system call loop from the application/program if it calls
  2942                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2943                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2944                              <1> 	;
  2945                              <1> 	; Note: syswait will return with error if there is not a
  2946                              <1> 	;       zombie or running process to wait.	
  2947                              <1> 	;
  2948                              <1> 	;sub	ax, ax
  2949                              <1> 	; 08/01/2022
  2950 00003CC9 29C0                <1> 	sub	eax, eax
  2951 00003CCB 668986[866D0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2952 00003CD2 E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2953                              <1> 	;
  2954                              <1> 	;jmp	sysret
  2955                              <1> 		; br sysret1 / return cause child is dead
  2956                              <1> syswait_2: ; 2:
  2957                              <1> 	; 09/02/2022
  2958 00003CD7 D1E6                <1> 	shl	esi, 1
  2959                              <1> 	;shl	si, 1
  2960                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2961                              <1> syswait_3: ; 3:
  2962 00003CD9 6683FE20            <1> 	cmp	si, nproc+nproc
  2963                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2964 00003CDD 72BE                <1> 	jb	short syswait_1
  2965                              <1> 		; blt 1b / no, continue search
  2966                              <1> 	;and	cx, cx
  2967 00003CDF 20C9                <1> 	and	cl, cl
  2968                              <1> 		; tst r3 / one gets here if there are no children 
  2969                              <1> 		       ; / or children that are still active
  2970                              <1> 	; 30/10/2013
  2971 00003CE1 7515                <1> 	jnz	short syswait_4
  2972                              <1> 	;jz	error
  2973                              <1> 		; beq error1 / there are no children, error
  2974 00003CE3 890D[4C700000]      <1> 	mov	[u.r0], ecx ; 0
  2975                              <1> 	; 09/02/2022
  2976 00003CE9 C705[A1700000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2976 00003CF1 0000                <1>
  2977                              <1> 			; miscellaneous/other errors
  2978 00003CF3 E9C7FDFFFF          <1> 	jmp	error
  2979                              <1> syswait_4:
  2980 00003CF8 8A1D[9B700000]      <1> 	mov	bl, [u.uno]
  2981                              <1> 		; movb u.uno,r1 / there are children so put 
  2982                              <1> 			      ; / parent process number in r1
  2983 00003CFE FE83[C76D0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2984                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2985                              <1> 				  ; / other children to die
  2986                              <1> 	; 04/11/2013
  2987 00003D04 E873110000          <1> 	call	swap
  2988                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2989 00003D09 E97BFFFFFF          <1> 	jmp	syswait_0
  2990                              <1> 		; br syswait / wait on next process
  2991                              <1> 
  2992                              <1> sysfork: ; < create a new process >
  2993                              <1> 	; 26/02/2022
  2994                              <1> 	; 25/02/2022
  2995                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2996                              <1> 	; 18/09/2015
  2997                              <1> 	; 04/09/2015
  2998                              <1> 	; 02/09/2015
  2999                              <1> 	; 01/09/2015
  3000                              <1> 	; 28/08/2015
  3001                              <1> 	; 14/05/2015
  3002                              <1> 	; 10/05/2015
  3003                              <1> 	; 09/05/2015
  3004                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3005                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3006                              <1> 	;
  3007                              <1> 	; 'sysfork' creates a new process. This process is referred
  3008                              <1> 	; to as the child process. This new process core image is
  3009                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3010                              <1> 	; distinction is the return location and the fact that (u.r0)
  3011                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3012                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3013                              <1> 	; 'sysfork' works in the following manner: 	
  3014                              <1> 	;    1) The process status table (p.stat) is searched to find
  3015                              <1> 	;	a process number that is unused. If none are found
  3016                              <1> 	;	an error occurs.
  3017                              <1> 	;    2) when one is found, it becomes the child process number
  3018                              <1> 	;	and it's status (p.stat) is set to active.
  3019                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3020                              <1> 	;	character in that tty buffer is cleared.
  3021                              <1> 	;    4) The child process is put on the lowest priority run 
  3022                              <1> 	;	queue via 'putlu'.
  3023                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3024                              <1> 	;	it is a unique number) and is put in the child's unique
  3025                              <1> 	;	identifier; process id (p.pid).
  3026                              <1> 	;    6) The process name of the parent is then obtained and
  3027                              <1> 	;	placed in the unique identifier of the parent process
  3028                              <1> 	;	name is then put in 'u.r0'.	
  3029                              <1> 	;    7) The child process is then written out on disk by
  3030                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3031                              <1> 	;	and the child is born. (The child process is written 
  3032                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3033                              <1> 	;	number.)
  3034                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3035                              <1> 	;    9) The child process name is put in 'u.r0'.
  3036                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3037                              <1> 	;	create the return address for the parent process.
  3038                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3039                              <1> 	;	the parent has opened. For each file the parent has
  3040                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3041                              <1> 	;	to indicate that the child process also has opened
  3042                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3043                              <1> 	;
  3044                              <1> 	; Calling sequence:
  3045                              <1> 	;	from shell ?
  3046                              <1> 	; Arguments:
  3047                              <1> 	;	-
  3048                              <1> 	; Inputs: -
  3049                              <1> 	; Outputs: *u.r0 - child process name
  3050                              <1> 	; ...............................................................
  3051                              <1> 	;	
  3052                              <1> 	; Retro UNIX 8086 v1 modification: 
  3053                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3054                              <1> 	;	= process id of child a parent process returns
  3055                              <1> 	;	= process id of parent when a child process returns
  3056                              <1> 	;
  3057                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3058                              <1> 	;	in following manner: (with an example: c library, fork)
  3059                              <1> 	;	
  3060                              <1> 	;	1:
  3061                              <1> 	;		sys	fork
  3062                              <1> 	;			br 1f  / child process returns here
  3063                              <1> 	;		bes	2f     / parent process returns here
  3064                              <1> 	;		/ pid of new process in r0
  3065                              <1> 	;		rts	pc
  3066                              <1> 	;	2: / parent process condionally branches here
  3067                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3068                              <1> 	;		rts	pc
  3069                              <1> 	;
  3070                              <1> 	;	1: / child process brances here
  3071                              <1> 	;		clr	r0   / pid = 0 in child process
  3072                              <1> 	;		rts	pc
  3073                              <1> 	;
  3074                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3075                              <1> 	;		// pid = fork();
  3076                              <1> 	;		//
  3077                              <1> 	;		// pid == 0 in child process; 
  3078                              <1> 	;		// pid == -1 means error return
  3079                              <1> 	;		// in child, 
  3080                              <1> 	;		//	parents id is in par_uid if needed
  3081                              <1> 	;		
  3082                              <1> 	;		_fork:
  3083                              <1> 	;			mov	$.fork,eax
  3084                              <1> 	;			int	$0x30
  3085                              <1> 	;			jmp	1f
  3086                              <1> 	;			jnc	2f
  3087                              <1> 	;			jmp	cerror
  3088                              <1> 	;		1:
  3089                              <1> 	;			mov	eax,_par_uid
  3090                              <1> 	;			xor	eax,eax
  3091                              <1> 	;		2:
  3092                              <1> 	;			ret
  3093                              <1> 	;
  3094                              <1> 	;	In Retro UNIX 8086 v1,
  3095                              <1> 	;	'sysfork' returns in following manner:
  3096                              <1> 	;	
  3097                              <1> 	;		mov	ax, sys_fork
  3098                              <1> 	;		mov	bx, offset @f ; routine for child
  3099                              <1> 	;		int	20h
  3100                              <1> 	;		jc	error
  3101                              <1> 	;		
  3102                              <1> 	;	; Routine for parent process here (just after 'jc')
  3103                              <1> 	;		mov	word ptr [pid_of_child], ax
  3104                              <1> 	;		jmp	next_routine_for_parent	
  3105                              <1> 	;
  3106                              <1> 	;	@@: ; routine for child process here				
  3107                              <1> 	;		....	
  3108                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3109                              <1> 	;	       for child process by using BX input.
  3110                              <1> 	;	      (at first, parent process will return then 
  3111                              <1> 	;	      child process will return -after swapped in-
  3112                              <1> 	;	      'syswait' is needed in parent process
  3113                              <1> 	;	      if return from child process will be waited for.)
  3114                              <1> 	;	  				
  3115                              <1> 	
  3116                              <1> ; / create a new process
  3117                              <1> 	; EBX = return address for child process 
  3118                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3119 00003D0E 31F6                <1> 	xor 	esi, esi
  3120                              <1> 		; clr r1
  3121                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3122 00003D10 46                  <1> 	inc	esi
  3123                              <1> 		; inc r1
  3124 00003D11 80BE[C76D0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3125                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3126 00003D18 760B                <1> 	jna	short sysfork_2	
  3127                              <1> 		; beq 1f / it's unused so branch
  3128 00003D1A 6683FE10            <1> 	cmp	si, nproc
  3129                              <1> 		; cmp r1,$nproc / all processes checked
  3130 00003D1E 72F0                <1> 	jb	short sysfork_1
  3131                              <1> 		; blt 1b / no, branch back
  3132                              <1> 	;
  3133                              <1> 	; Retro UNIX 8086 v1. modification:
  3134                              <1> 	;	Parent process returns from 'sysfork' to address 
  3135                              <1> 	;	which is just after 'sysfork' system call in parent
  3136                              <1> 	;	process. Child process returns to address which is put
  3137                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3138                              <1> 	;
  3139                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3140                              <1> 		             ; / to old process return
  3141                              <1> 		; br error1 / no room for a new process
  3142                              <1> sysfork_0:
  3143 00003D20 E99AFDFFFF          <1> 	jmp	error
  3144                              <1> sysfork_2: ; 1:
  3145 00003D25 E884F0FFFF          <1> 	call	allocate_page
  3146                              <1> 	;jc	error
  3147                              <1> 	; 08/01/2022
  3148 00003D2A 72F4                <1> 	jc	short sysfork_0
  3149                              <1> 
  3150 00003D2C 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3151                              <1> 	; Retro UNIX 386 v1 modification!
  3152 00003D2D E875F2FFFF          <1> 	call	duplicate_page_dir
  3153                              <1> 		; EAX = New page directory 
  3154 00003D32 7308                <1> 	jnc	short sysfork_3
  3155 00003D34 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3156 00003D35 E83CF2FFFF          <1> 	call 	deallocate_page
  3157                              <1> 	;jmp	error
  3158                              <1> 	; 08/01/2022
  3159 00003D3A EBE4                <1> 	jmp	short sysfork_0 ; error
  3160                              <1> sysfork_3:
  3161                              <1> 	; Retro UNIX 386 v1 modification !
  3162 00003D3C 56                  <1> 	push	esi
  3163 00003D3D E8B1110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3164                              <1> 		      ; and interrupt return components (for IRET)
  3165 00003D42 8705[A5700000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3166 00003D48 A3[A9700000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3167 00003D4D 5E                  <1> 	pop	esi
  3168 00003D4E 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3169                              <1> 		; [u.usp] = esp
  3170 00003D4F 89F7                <1> 	mov	edi, esi
  3171                              <1> 	;shl	di, 2
  3172                              <1> 	; 08/01/2022
  3173 00003D51 C1E702              <1> 	shl	edi, 2
  3174 00003D54 8987[D46D0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3175 00003D5A A3[9C700000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3176                              <1> 	; 28/08/2015
  3177 00003D5F 0FB605[9B700000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3178                              <1> 		; movb u.uno,-(sp) / save parent process number
  3179 00003D66 89C7                <1> 	mov	edi, eax
  3180 00003D68 50                  <1>         push	eax ; ** 
  3181 00003D69 8A87[A76D0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3182                              <1> 		; 18/09/2015
  3183 00003D6F 8886[A76D0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3184                              <1> 	; 26/02/2022 (p.waitc is not used)
  3185                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3186                              <1> 	; 25/02/2022 (BugFix)
  3187                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3188                              <1> 	;			   ; ah - reset child's wait channel	
  3189 00003D75 89F0                <1> 	mov	eax, esi
  3190 00003D77 A2[9B700000]        <1> 	mov	[u.uno], al ; child process number
  3191                              <1> 		;movb r1,u.uno / set child process number to r1
  3192 00003D7C FE86[C76D0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3193                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3194                              <1> 				; / process to active status
  3195                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3196                              <1> 			      ; / control tty buffer in r2
  3197                              <1>                 ; beq 2f / branch, if no such tty assigned
  3198                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3199                              <1> 	; 2:
  3200 00003D82 53                  <1> 	push	ebx  ; * return address for the child process
  3201                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3202                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3203                              <1> 		; mov $runq+4,r2
  3204 00003D83 E8C1110000          <1> 	call	putlu 
  3205                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3206                              <1> 			   ; / run queue
  3207                              <1> 	; 08/01/2022
  3208 00003D88 D1E6                <1> 	shl	esi, 1
  3209                              <1> 	;shl	si, 1
  3210                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3211                              <1> 		       ; / into p.pid table
  3212 00003D8A 66FF05[38700000]    <1> 	inc	word [mpid]
  3213                              <1> 		; inc mpid / increment m.pid; get a new process name
  3214 00003D91 66A1[38700000]      <1> 	mov	ax, [mpid]
  3215 00003D97 668986[666D0000]    <1> 	mov	[esi+p.pid-2], ax
  3216                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3217                              <1> 				    ; / in child process' name slot
  3218 00003D9E 5A                  <1> 	pop	edx  ; * return address for the child process
  3219                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3220 00003D9F 5B                  <1>   	pop	ebx  ; **
  3221                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3222                              <1> 		; movb (sp),r2 / put parent process number in r2
  3223                              <1> 	; 08/01/2022
  3224 00003DA0 D1E3                <1> 	shl	ebx, 1
  3225                              <1> 	;shl 	bx, 1
  3226                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3227                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3228 00003DA2 668B83[666D0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3229                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3230                              <1> 				   ; / process
  3231 00003DA9 668986[866D0000]    <1> 	mov	[esi+p.ppid-2], ax
  3232                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3233                              <1> 			  ; / in parent process slot for child
  3234 00003DB0 A3[4C700000]        <1> 	mov	[u.r0], eax	
  3235                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3236                              <1> 			     ; / at location where r0 was saved
  3237 00003DB5 8B2D[44700000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3238 00003DBB 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3239                              <1> 			   ; * return address for the child process
  3240                              <1> 		; mov $sysret1,-(sp) /
  3241                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3242                              <1> 			      ; / user is swapped out
  3243                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3244                              <1> 	; 04/09/2015 - 01/09/2015
  3245                              <1> 	; [u.usp] = esp
  3246 00003DBE 68[DF3A0000]        <1> 	push	sysret ; ***
  3247 00003DC3 8925[48700000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3248                              <1> 			     ; (for child process)	
  3249 00003DC9 31C0                <1> 	xor 	eax, eax
  3250 00003DCB 66A3[7C700000]      <1> 	mov 	[u.ttyp], ax ; 0
  3251                              <1> 	;
  3252 00003DD1 E81D110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3253                              <1> 		;jsr r0,wswap / put child process out on drum
  3254                              <1> 		;jsr r0,unpack / unpack user stack
  3255                              <1> 		;mov u.usp,sp / restore user stack pointer
  3256                              <1> 		; tst (sp)+ / bump stack pointer
  3257                              <1> 	; Retro UNIX 386 v1 modification !
  3258 00003DD6 58                  <1> 	pop	eax ; ***
  3259                              <1> 	; 08/01/2022
  3260 00003DD7 D1E3                <1> 	shl	ebx, 1
  3261                              <1> 	;shl 	bx, 1
  3262 00003DD9 8B83[D46D0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3263 00003DDF E838110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3264                              <1> 		      ; registers and return address (for IRET)
  3265                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3266 00003DE4 0FB705[38700000]    <1>         movzx   eax, word [mpid]
  3267 00003DEB A3[4C700000]        <1> 	mov	[u.r0], eax
  3268                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3269                              <1> 			       ; / where r0 was saved
  3270                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3271                              <1> 			          ; / process return
  3272                              <1> 	;xor	ebx, ebx
  3273 00003DF0 31F6                <1> 	xor     esi, esi
  3274                              <1> 		;clr r1
  3275                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3276                              <1> 	      ; / opened by the parent process
  3277                              <1> 	; 01/09/2015
  3278                              <1> 	;xor	bh, bh
  3279                              <1> 	;mov 	bl, [esi+u.fp]
  3280 00003DF2 8A86[52700000]      <1> 	mov 	al, [esi+u.fp]
  3281                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3282                              <1>         ;or	bl, bl
  3283 00003DF8 08C0                <1> 	or	al, al
  3284 00003DFA 740C                <1> 	jz	short sysfork_5	
  3285                              <1> 		; beq 2f / file has not been opened by parent, 
  3286                              <1> 		       ; / so branch
  3287 00003DFC B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3288 00003DFE F6E4                <1> 	mul	ah
  3289                              <1> 	;;movzx	ebx, ax
  3290                              <1> 	;mov	bx, ax
  3291 00003E00 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3292                              <1> 	;shl	bx, 3
  3293                              <1> 		; asl r2 / multiply by 8
  3294                              <1>        		; asl r2 / to get index into fsp table
  3295                              <1>        		; asl r2
  3296 00003E02 FE83[166E0000]      <1>   	inc     byte [ebx+fsp-2]
  3297                              <1> 		; incb fsp-2(r2) / increment number of processes
  3298                              <1> 			     ; / using file, because child will now be
  3299                              <1> 			     ; / using this file
  3300                              <1> sysfork_5: ; 2:
  3301 00003E08 46                  <1>         inc     esi
  3302                              <1> 		; inc r1 / get next open file
  3303 00003E09 6683FE0A            <1>         cmp     si, 10
  3304                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3305                              <1> 			  ; / can be opened
  3306 00003E0D 72E3                <1> 	jb	short sysfork_4	
  3307                              <1> 		; blt 1b / check next entry
  3308 00003E0F E9CBFCFFFF          <1> 	jmp	sysret
  3309                              <1> 		; br sysret1
  3310                              <1> 
  3311                              <1> sysread: ; < read from file >
  3312                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3313                              <1> 	; 13/05/2015
  3314                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3315                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3316                              <1> 	;
  3317                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3318                              <1> 	; characters to be read. If finds the file from the file
  3319                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3320                              <1> 	; is returned from a successful open call (sysopen).
  3321                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3322                              <1> 	; is read into core via 'readi'.
  3323                              <1> 	;
  3324                              <1> 	; Calling sequence:
  3325                              <1> 	;	sysread; buffer; nchars
  3326                              <1> 	; Arguments:
  3327                              <1> 	;	buffer - location of contiguous bytes where 
  3328                              <1> 	;		 input will be placed.
  3329                              <1> 	;	nchars - number of bytes or characters to be read.
  3330                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3331                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3332                              <1> 	; ...............................................................
  3333                              <1> 	;				
  3334                              <1> 	; Retro UNIX 8086 v1 modification: 
  3335                              <1> 	;       'sysread' system call has three arguments; so,
  3336                              <1> 	;	* 1st argument, file descriptor is in BX register
  3337                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3338                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3339                              <1> 	;
  3340                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3341                              <1> 	;	to the user with number of bytes read. 
  3342                              <1> 	;
  3343 00003E14 E840000000          <1> 	call	rw1
  3344                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3345                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3346                              <1>        	; 24/12/2021
  3347 00003E19 7239                <1> 	jc	short sysread_err
  3348 00003E1B F6C480              <1> 	test	ah, 80h
  3349                              <1> 		; tst r1 / negative i-number?
  3350 00003E1E 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3351                              <1> 	;jnz	error
  3352                              <1> 		; ble error1 / yes, error 1 to read
  3353                              <1> 			   ; / it should be positive
  3354 00003E20 E88B150000          <1> 	call	readi
  3355                              <1> 		; jsr r0,readi / read data into core
  3356 00003E25 EB14                <1> 	jmp	short rw0
  3357                              <1> 		; br 1f
  3358                              <1> 
  3359                              <1> syswrite: ; < write to file >
  3360                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3361                              <1> 	; 13/05/2015
  3362                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3363                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3364                              <1> 	;
  3365                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3366                              <1> 	; and the number of characters to write. If finds the file
  3367                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3368                              <1> 	; descriptor is returned from a successful open or create call
  3369                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3370                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3371                              <1> 	;
  3372                              <1> 	; Calling sequence:
  3373                              <1> 	;	syswrite; buffer; nchars
  3374                              <1> 	; Arguments:
  3375                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3376                              <1> 	;	nchars - number of characters to be written.
  3377                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3378                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3379                              <1> 	; ...............................................................
  3380                              <1> 	;				
  3381                              <1> 	; Retro UNIX 8086 v1 modification: 
  3382                              <1> 	;       'syswrite' system call has three arguments; so,
  3383                              <1> 	;	* 1st argument, file descriptor is in BX register
  3384                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3385                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3386                              <1> 	;
  3387                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3388                              <1> 	;	to the user with number of bytes written. 
  3389                              <1> 	;
  3390 00003E27 E82D000000          <1> 	call	rw1
  3391                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3392                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3393                              <1>        	; 24/12/2021
  3394 00003E2C 7226                <1> 	jc	short syswrite_err
  3395 00003E2E F6C480              <1>         test	ah, 80h
  3396                              <1> 		; tst r1 / positive i-number ?
  3397 00003E31 7417                <1>         jz	short rw3 ; 13/05/2015
  3398                              <1> 	;jz	error
  3399                              <1> 		; bge error1 / yes, error 1 
  3400                              <1> 			   ; / negative i-number means write
  3401 00003E33 66F7D8              <1>         neg	ax
  3402                              <1> 		; neg r1 / make it positive
  3403 00003E36 E863170000          <1> 	call	writei
  3404                              <1>         	; jsr r0,writei / write data
  3405                              <1> rw0: ; 1:
  3406 00003E3B A1[74700000]        <1>         mov	eax, [u.nread]
  3407 00003E40 A3[4C700000]        <1> 	mov	[u.r0], eax
  3408                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3409                              <1> 				  ; / into (u.r0)
  3410 00003E45 E995FCFFFF          <1> 	jmp	sysret
  3411                              <1>         	; br sysret1
  3412                              <1> 
  3413                              <1> rw3: 
  3414                              <1> 	; 13/05/2015
  3415 00003E4A C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3415 00003E52 0000                <1>
  3416                              <1> 	;stc
  3417                              <1> 	;retn
  3418                              <1> 	; 24/12/2021 (BugFix)
  3419                              <1> sysread_err:
  3420                              <1> syswrite_err:
  3421 00003E54 E966FCFFFF          <1> 	jmp	error
  3422                              <1> 
  3423                              <1> rw1:	
  3424                              <1> 	; 14/05/2015
  3425                              <1> 	; 13/05/2015
  3426                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3427                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3428                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3429                              <1> 	;
  3430                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3431                              <1> 				;(in the user's virtual memory space)
  3432                              <1> 	;mov	[u.count], edx 
  3433                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3434                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3435                              <1> 	;;mov	eax, ebx ; file descriptor
  3436                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3437                              <1> 		             ; / (index to u.fp table) in r1
  3438                              <1> 	; 13/05/2015
  3439 00003E59 C705[4C700000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3439 00003E61 0000                <1>
  3440                              <1> 	;
  3441                              <1> 	;; call	getf
  3442                              <1>         ; eBX = File descriptor
  3443 00003E63 E8330B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3444                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3445                              <1> 	; AX = I-number of the file ; negative i-number means write
  3446                              <1> 	; 13/05/2015
  3447 00003E68 6683F801            <1> 	cmp 	ax, 1
  3448 00003E6C 7217                <1> 	jb	short rw2
  3449                              <1> 	;
  3450 00003E6E 890D[6C700000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3451                              <1> 				;(in the user's virtual memory space)
  3452 00003E74 8915[70700000]      <1> 	mov	[u.count], edx 
  3453                              <1> 	; 14/05/2015
  3454 00003E7A C705[A1700000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3454 00003E82 0000                <1>
  3455 00003E84 C3                  <1> 	retn
  3456                              <1>         	; rts r0
  3457                              <1> rw2:
  3458                              <1> 	; 13/05/2015
  3459 00003E85 C705[A1700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3459 00003E8D 0000                <1>
  3460 00003E8F C3                  <1> 	retn
  3461                              <1> 
  3462                              <1> sysopen: ;<open file>
  3463                              <1> 	; 09/01/2022
  3464                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3465                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3466                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3467                              <1> 	;
  3468                              <1> 	; 'sysopen' opens a file in following manner:
  3469                              <1> 	;    1) The second argument in a sysopen says whether to
  3470                              <1> 	;	open the file ro read (0) or write (>0).
  3471                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3472                              <1> 	;    3) The file is opened by 'iopen'.
  3473                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3474                              <1> 	;	and the user's open file list - u.fp.
  3475                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3476                              <1> 	;	b) An entry for the file is created in the fsp table.
  3477                              <1> 	;	c) The number of this entry is put on u.fp list.
  3478                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3479                              <1> 	;	   to by u.r0.
  3480                              <1> 	;
  3481                              <1> 	; Calling sequence:
  3482                              <1> 	;	sysopen; name; mode
  3483                              <1> 	; Arguments:
  3484                              <1> 	;	name - file name or path name
  3485                              <1> 	;	mode - 0 to open for reading
  3486                              <1> 	;	       1 to open for writing
  3487                              <1> 	; Inputs: (arguments)
  3488                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3489                              <1> 	;		  is put into r0's location on the stack.	
  3490                              <1> 	; ...............................................................
  3491                              <1> 	;				
  3492                              <1> 	; Retro UNIX 8086 v1 modification: 
  3493                              <1> 	;       'sysopen' system call has two arguments; so,
  3494                              <1> 	;	* 1st argument, name is pointed to by BX register
  3495                              <1> 	;	* 2nd argument, mode is in CX register
  3496                              <1> 	;
  3497                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3498                              <1> 	;	to the user with the file descriptor/number 
  3499                              <1> 	;	(index to u.fp list).
  3500                              <1> 	;
  3501                              <1> 	;call	arg2
  3502                              <1> 	; * name - 'u.namep' points to address of file/path name
  3503                              <1> 	;          in the user's program segment ('u.segmnt')
  3504                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3505                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3506                              <1> 	;          which is on top of stack.
  3507                              <1> 	;
  3508                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3509                              <1> 	;
  3510                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3511                              <1> 
  3512 00003E90 891D[64700000]      <1> 	mov	[u.namep], ebx
  3513                              <1> 	; 24/12/2021 (cx -> ecx)
  3514 00003E96 51                  <1> 	push	ecx ; * 
  3515 00003E97 E8300B0000          <1> 	call	namei
  3516                              <1> 		; jsr r0,namei / i-number of file in r1
  3517                              <1>      	;and	ax, ax
  3518                              <1> 	;jz	error ; File not found
  3519 00003E9C 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3520                              <1> 	;jc	error ; 27/05/2013
  3521                              <1> 		; br  error2 / file not found
  3522                              <1>    	; 24/12/2021
  3523                              <1> 	;pop	edx ; * ; mode
  3524                              <1> 	;push	edx ; *
  3525 00003E9E 8B1424              <1> 	mov	edx, [esp] ; *
  3526                              <1> 	; edx = open mode (0 or 1)
  3527                              <1> 	;or	dx, dx
  3528 00003EA1 08D2                <1> 	or	dl, dl
  3529                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3530                              <1> 		         ; / 0 means, open for read)
  3531 00003EA3 7403                <1> 	jz	short sysopen_0
  3532                              <1> 		; beq 1f / yes, leave i-number positive
  3533                              <1> syscreat_0: ; 27/12/2015
  3534 00003EA5 66F7D8              <1> 	neg	ax
  3535                              <1>         	; neg r1 / open for writing so make i-number negative
  3536                              <1> sysopen_0: ;1:
  3537 00003EA8 E8891B0000          <1> 	call	iopen
  3538                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3539 00003EAD 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3540                              <1> 	;and	dx, dx
  3541 00003EAE 20D2                <1> 	and	dl, dl
  3542                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3543 00003EB0 7403                <1> 	jz	short sysopen_2
  3544                              <1>         	; beq op1 / is open for read op1
  3545                              <1> sysopen_1: ;op0:
  3546 00003EB2 66F7D8              <1> 	neg	ax
  3547                              <1>         	; neg r1 
  3548                              <1> 	;; NOTE: iopen always make i-number positive.
  3549                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3550                              <1> sysopen_2: ;op1:
  3551 00003EB5 31F6                <1>         xor     esi, esi
  3552                              <1>         	; clr r2 / clear registers
  3553 00003EB7 31DB                <1>         xor     ebx, ebx
  3554                              <1> 		; clr r3
  3555                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3556 00003EB9 389E[52700000]      <1>         cmp     [esi+u.fp], bl ; 0
  3557                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3558 00003EBF 7625                <1>         jna      short sysopen_4
  3559                              <1> 		; beq 1f / if byte in list is 0 branch
  3560 00003EC1 46                  <1>         inc     esi
  3561                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3562 00003EC2 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3563                              <1> 		; cmp r2,$10. / reached end of list?
  3564 00003EC6 72F1                <1> 	jb	short sysopen_3
  3565                              <1> 		; blt 1b / no, go back
  3566                              <1> toomanyf:
  3567                              <1> 	; 14/05/2015
  3568 00003EC8 C705[A1700000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3568 00003ED0 0000                <1>
  3569 00003ED2 E9E8FBFFFF          <1> 	jmp	error
  3570                              <1>         	; br error2 / yes, error (no files open)
  3571                              <1> fnotfound: 
  3572                              <1> 	; 14/05/2015
  3573 00003ED7 C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3573 00003EDF 0000                <1>
  3574 00003EE1 E9D9FBFFFF          <1> 	jmp	error
  3575                              <1> 
  3576                              <1> sysopen_4: ; 1:
  3577 00003EE6 6683BB[186E0000]00  <1>         cmp     word [ebx+fsp], 0
  3578                              <1> 		; tst fsp(r3) / scan fsp entries
  3579 00003EEE 760D                <1>         jna     short sysopen_5
  3580                              <1> 		; beq 1f / if 0 branch
  3581                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3582 00003EF0 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3583                              <1> 		; add $8.,r3 / add 8 to r3 
  3584                              <1> 			; / to bump it to next entry mfsp table
  3585 00003EF4 6681FBF401          <1>         cmp     bx, nfiles*10
  3586                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3587 00003EF9 72EB                <1> 	jb	short sysopen_4
  3588                              <1>        		; blt 1b / no, back
  3589                              <1> 	;jmp	error
  3590                              <1>         ;	; br error2 / yes, error
  3591                              <1> 	; 24/12/2021
  3592 00003EFB EBCB                <1> 	jmp	short toomanyf
  3593                              <1> 
  3594                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3595 00003EFD 668983[186E0000]    <1>         mov     [ebx+fsp], ax
  3596                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3597                              <1> 			; / into next available entry in fsp table,
  3598                              <1> 	; 09/01/2022
  3599                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3600                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3601                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3602                              <1> 	;xor	edi, edi
  3603                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3604                              <1> 	;	; clr fsp+4(r3)
  3605                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3606                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3607 00003F04 31C0                <1> 	xor	eax, eax
  3608 00003F06 8983[1C6E0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3609 00003F0C 668983[206E0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3610                              <1> 
  3611 00003F13 A0[2F700000]        <1> 	mov	al, [cdev]
  3612 00003F18 668983[1A6E0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3613                              <1> 
  3614 00003F1F 89D8                <1>   	mov	eax, ebx
  3615 00003F21 B30A                <1> 	mov	bl, 10
  3616 00003F23 F6F3                <1> 	div	bl 
  3617                              <1> 		; asr r3
  3618                              <1> 		; asr r3 / divide by 8 
  3619                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3620 00003F25 FEC0                <1> 	inc	al
  3621                              <1>         	; inc r3 / add 1 to get fsp entry number
  3622 00003F27 8886[52700000]      <1>         mov     [esi+u.fp], al
  3623                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3624                              <1> 			; / next available slot in u.fp list
  3625 00003F2D 8935[4C700000]      <1>         mov     [u.r0], esi
  3626                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3627                              <1> 			     ; / into r0 loc on stack
  3628 00003F33 E9A7FBFFFF          <1>         jmp	sysret
  3629                              <1> 		; br sysret2
  3630                              <1> 
  3631                              <1> 	;
  3632                              <1> 	; 'fsp' table (10 bytes/entry)
  3633                              <1> 	; bit 15				   bit 0
  3634                              <1> 	; ---|-------------------------------------------
  3635                              <1> 	; r/w|		i-number of open file
  3636                              <1> 	; ---|-------------------------------------------
  3637                              <1> 	;		   device number
  3638                              <1> 	; -----------------------------------------------
  3639                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3640                              <1> 	; -----------------------------------------------
  3641                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3642                              <1> 	; ----------------------|------------------------
  3643                              <1> 	;  flag that says file 	| number of processes
  3644                              <1> 	;   has been deleted	| that have file open 
  3645                              <1> 	; ----------------------|------------------------
  3646                              <1> 	;
  3647                              <1> 
  3648                              <1> syscreat: ; < create file >
  3649                              <1> 	; 24/12/2021
  3650                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3651                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3652                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3653                              <1> 	;
  3654                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3655                              <1> 	; u.namep points to name of the file and mode is put
  3656                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3657                              <1> 	; If the file aready exists, it's mode and owner remain 
  3658                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3659                              <1> 	; did not exist, an i-node is created with the new mode via
  3660                              <1> 	; 'maknod' whether or not the file already existed, it is
  3661                              <1> 	; open for writing. The fsp table is then searched for a free
  3662                              <1> 	; entry. When a free entry is found, proper data is placed
  3663                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3664                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3665                              <1> 	; is put in the user's r0. 			
  3666                              <1> 	;
  3667                              <1> 	; Calling sequence:
  3668                              <1> 	;	syscreate; name; mode
  3669                              <1> 	; Arguments:
  3670                              <1> 	;	name - name of the file to be created
  3671                              <1> 	;	mode - mode of the file to be created
  3672                              <1> 	; Inputs: (arguments)
  3673                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3674                              <1> 	;		   (the file descriptor of new file)
  3675                              <1> 	; ...............................................................
  3676                              <1> 	;				
  3677                              <1> 	; Retro UNIX 8086 v1 modification: 
  3678                              <1> 	;       'syscreate' system call has two arguments; so,
  3679                              <1> 	;	* 1st argument, name is pointed to by BX register
  3680                              <1> 	;	* 2nd argument, mode is in CX register
  3681                              <1> 	;
  3682                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3683                              <1> 	;	to the user with the file descriptor/number 
  3684                              <1> 	;	(index to u.fp list).
  3685                              <1> 	;
  3686                              <1> 	;call	arg2
  3687                              <1> 	; * name - 'u.namep' points to address of file/path name
  3688                              <1> 	;          in the user's program segment ('u.segmnt')
  3689                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3690                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3691                              <1> 	;          which is on top of stack.
  3692                              <1> 	;
  3693                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3694                              <1> 			    ; / on stack
  3695 00003F38 891D[64700000]      <1> 	mov	[u.namep], ebx ; file name address
  3696                              <1> 	;push	cx ; mode
  3697                              <1> 	; 24/12/2021
  3698 00003F3E 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3699 00003F3F E8880A0000          <1> 	call 	namei        	
  3700                              <1> 		; jsr r0,namei / get the i-number
  3701                              <1>         ;and	ax, ax
  3702                              <1> 	;jz	short syscreat_2	       	
  3703 00003F44 721B                <1> 	jc	short syscreat_2
  3704                              <1> 		; br  2f / if file doesn't exist 2f
  3705                              <1> 	; 27/12/2015
  3706 00003F46 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3707                              <1>         ;jb	syscreat_0 ; yes
  3708                              <1> 	; 24/12/2021
  3709 00003F4A 7305                <1> 	jnb	short syscreat_1
  3710 00003F4C E954FFFFFF          <1> 	jmp	syscreat_0
  3711                              <1> syscreat_1:
  3712 00003F51 66F7D8              <1> 	neg 	ax
  3713                              <1>         	; neg r1 / if file already exists make i-number 
  3714                              <1> 		       ; / negative (open for writing)
  3715 00003F54 E8DD1A0000          <1> 	call	iopen
  3716                              <1>         	; jsr r0,iopen /
  3717 00003F59 E8AA130000          <1> 	call	itrunc
  3718                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3719                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3720                              <1> 	; 04/12/2021
  3721 00003F5E 59                  <1> 	pop	ecx
  3722                              <1> 	; 08/01/2022
  3723 00003F5F EB0E                <1> 	jmp	short syscreat_3
  3724                              <1>         ;jmp	sysopen_1
  3725                              <1>         	; br op0
  3726                              <1> syscreat_2: ; 2: / file doesn't exist
  3727                              <1> 	;pop	ax
  3728                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3729                              <1> 	; 24/12/2021
  3730 00003F61 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3731 00003F62 30E4                <1> 	xor	ah, ah	
  3732                              <1>         	; bic $!377,r1 / clear upper byte
  3733 00003F64 E86F0D0000          <1> 	call 	maknod
  3734                              <1>         	; jsr r0,maknod / make an i-node for this file
  3735 00003F69 66A1[7E700000]      <1> 	mov	ax, [u.dirbuf]
  3736                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3737                              <1> 			        ; / for this new file in r1
  3738                              <1> syscreat_3:
  3739 00003F6F E93EFFFFFF          <1>         jmp     sysopen_1
  3740                              <1>         	; br op0 / open the file
  3741                              <1> 
  3742                              <1> sysmkdir: ; < make directory >
  3743                              <1> 	; 26/02/2022
  3744                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3745                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3746                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3747                              <1> 	;
  3748                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3749                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3750                              <1> 	; The special entries '.' and '..' are not present.
  3751                              <1> 	; Errors are indicated if the directory already exists or		
  3752                              <1> 	; user is not the super user. 
  3753                              <1> 	;
  3754                              <1> 	; Calling sequence:
  3755                              <1> 	;	sysmkdir; name; mode
  3756                              <1> 	; Arguments:
  3757                              <1> 	;	name - points to the name of the directory
  3758                              <1> 	;	mode - mode of the directory
  3759                              <1> 	; Inputs: (arguments)
  3760                              <1> 	; Outputs: -
  3761                              <1> 	;    (sets 'directory' flag to 1; 
  3762                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3763                              <1> 	; ...............................................................
  3764                              <1> 	;				
  3765                              <1> 	; Retro UNIX 8086 v1 modification: 
  3766                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3767                              <1> 	;	* 1st argument, name is pointed to by BX register
  3768                              <1> 	;	* 2nd argument, mode is in CX register
  3769                              <1> 	;
  3770                              <1> 		
  3771                              <1> ; / make a directory
  3772                              <1> 
  3773                              <1> 	;call	arg2
  3774                              <1> 	; * name - 'u.namep' points to address of file/path name
  3775                              <1> 	;          in the user's program segment ('u.segmnt')
  3776                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3777                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3778                              <1> 	;          which is on top of stack.
  3779                              <1> 
  3780                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3781                              <1> 			    ; / on stack
  3782 00003F74 891D[64700000]      <1> 	mov	[u.namep], ebx
  3783                              <1> 	;push	cx ; mode
  3784                              <1> 	; 24/12/2021
  3785 00003F7A 51                  <1> 	push	ecx ; cx = mode
  3786 00003F7B E84C0A0000          <1> 	call	namei
  3787                              <1>         	; jsr r0,namei / get the i-number
  3788                              <1>         	;     br .+4 / if file not found branch around error
  3789                              <1>         ;xor 	ax, ax
  3790                              <1> 	;jnz	error
  3791 00003F80 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3792                              <1> 	;jnc	error	
  3793                              <1> 		; br  error2 / directory already exists (error)
  3794 00003F82 803D[98700000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3795                              <1>         	;tstb u.uid / is user the super user
  3796                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3797                              <1> 	;;jna	error
  3798                              <1> 	; 26/02/2022 (BugFix)
  3799 00003F89 7721                <1> 	ja	short dir_access_err
  3800                              <1>         	;bne error2 / no, not allowed
  3801                              <1> 	;pop	ax
  3802                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3803                              <1> 	; 24/12/2021
  3804 00003F8B 58                  <1> 	pop	eax  ; ax = mode
  3805 00003F8C 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3806                              <1>         	;bic $!317,r1 / all but su and ex
  3807                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3808 00003F90 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3809                              <1>         	;bis $40000,r1 / directory flag
  3810 00003F93 E8400D0000          <1> 	call	maknod
  3811                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3812                              <1> ;sysclose_sysret: ; 26/02/2022
  3813 00003F98 E942FBFFFF          <1> 	jmp	sysret
  3814                              <1>         	;br sysret2 /
  3815                              <1> dir_exists:
  3816                              <1> 	; 14/05/2015
  3817 00003F9D C705[A1700000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3817 00003FA5 0000                <1>
  3818 00003FA7 E913FBFFFF          <1> 	jmp	error
  3819                              <1> dir_access_err:
  3820                              <1> 	; 14/05/2015
  3821 00003FAC C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3821 00003FB4 0000                <1>
  3822 00003FB6 E904FBFFFF          <1> 	jmp	error
  3823                              <1> 
  3824                              <1> sysclose: ;<close file>
  3825                              <1> 	; 26/02/2022
  3826                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3827                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3828                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3829                              <1> 	;
  3830                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3831                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3832                              <1> 	; is put in r1 and 'fclose' is called.
  3833                              <1> 	;
  3834                              <1> 	; Calling sequence:
  3835                              <1> 	;	sysclose
  3836                              <1> 	; Arguments:
  3837                              <1> 	;	-  
  3838                              <1> 	; Inputs: *u.r0 - file descriptor
  3839                              <1> 	; Outputs: -
  3840                              <1> 	; ...............................................................
  3841                              <1> 	;				
  3842                              <1> 	; Retro UNIX 8086 v1 modification:
  3843                              <1> 	;	 The user/application program puts file descriptor
  3844                              <1> 	;        in BX register as 'sysclose' system call argument.
  3845                              <1> 	; 	 (argument transfer method 1)
  3846                              <1> 
  3847                              <1> 	; / close the file
  3848                              <1> 	
  3849 00003FBB 89D8                <1> 	mov 	eax, ebx
  3850 00003FBD E896090000          <1> 	call 	fclose
  3851                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3852                              <1> 		; jsr r0,fclose / close the file
  3853                              <1>                	; br error2 / unknown file descriptor
  3854                              <1> 		; br sysret2
  3855                              <1> 	; 14/05/2015
  3856                              <1> 	;jnc	sysret
  3857                              <1> 	; 04/12/2021
  3858 00003FC2 7205                <1> 	jc	short sysclose_err
  3859 00003FC4 E916FBFFFF          <1> 	jmp	sysret
  3860                              <1> 	; 26/02/2022
  3861                              <1> 	;jnc	short sysclose_sysret
  3862                              <1> sysclose_err:
  3863 00003FC9 C705[A1700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3863 00003FD1 0000                <1>
  3864 00003FD3 E9E7FAFFFF          <1> 	jmp	error
  3865                              <1> 
  3866                              <1> sysemt:
  3867                              <1> 	; 26/02/2022
  3868                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3869                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3870                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3871                              <1> 	;
  3872                              <1> 	; Retro UNIX 8086 v1 modification: 
  3873                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3874                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3875                              <1> 	;
  3876                              <1> 	; Retro UNIX 8086 v1 feature only!
  3877                              <1> 	;	Using purpose: Kernel will start without time-out
  3878                              <1> 	;	(internal clock/timer) functionality.
  3879                              <1> 	;	Then etc/init will enable clock/timer for
  3880                              <1> 	;	multi tasking. (Then it will not be disabled again
  3881                              <1> 	;	except hardware reset/restart.)
  3882                              <1> 	;
  3883                              <1> 
  3884 00003FD8 803D[98700000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3885                              <1> 	;;ja	error
  3886                              <1> 	;ja	badsys ; 14/05/2015
  3887                              <1> 	; 24/12/2021
  3888 00003FDF 7605                <1> 	jna	short emt_0 
  3889 00003FE1 E98BFBFFFF          <1> 	jmp	badsys
  3890                              <1> emt_0:
  3891                              <1> 	; 24/12/2021
  3892                              <1> 	;cli
  3893 00003FE6 21DB                <1> 	and	ebx, ebx
  3894 00003FE8 7429                <1> 	jz	short emt_2
  3895                              <1> 	; Enable multi tasking -time sharing-
  3896 00003FEA B8[914F0000]        <1> 	mov	eax, clock
  3897                              <1> 	; 26/02/2022
  3898 00003FEF BA[4B0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3899                              <1> emt_1:
  3900 00003FF4 A3[10070000]        <1> 	mov	[x_timer], eax
  3901                              <1> 	; 26/02/2022 (Temporary)
  3902 00003FF9 8915[14070000]      <1> 	mov	[x_rtci], edx
  3903 00003FFF B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3904 00004001 E851020000          <1> 	call	wttyc  ; clear video page
  3905 00004006 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3906 00004008 E84A020000          <1> 	call	wttyc  ; clear video page
  3907                              <1> 	;
  3908 0000400D FB                  <1> 	sti
  3909 0000400E E9CCFAFFFF          <1> 	jmp	sysret
  3910                              <1> emt_2:
  3911                              <1> 	; Disable multi tasking -time sharing-
  3912 00004013 B8[1C070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3913                              <1> 	; 26/02/2022
  3914 00004018 BA[520A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3915                              <1> 	;
  3916 0000401D EBD5                <1> 	jmp	short emt_1
  3917                              <1> 
  3918                              <1> 	; Original UNIX v1 'sysemt' routine
  3919                              <1> ;sysemt:
  3920                              <1>         ;
  3921                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3922                              <1> 			 ; / in loc 30
  3923                              <1>         ;cmp    30,$core / was the argument a lower address 
  3924                              <1> 			; / than core
  3925                              <1>         ;blo    1f / yes, rtssym
  3926                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3927                              <1> 			; / and less than "ecore"
  3928                              <1>         ;blo    2f / yes, sysret2
  3929                              <1> ;1:
  3930                              <1>         ;mov    $rtssym,30
  3931                              <1> ;2:
  3932                              <1>         ;br     sysret2
  3933                              <1> 
  3934                              <1> sysilgins:
  3935                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3936                              <1> 	; 03/06/2013
  3937                              <1> 	; Retro UNIX 8086 v1 modification: 
  3938                              <1> 	;	not a valid system call ! (not in use)
  3939                              <1> 	;
  3940 0000401F E94DFBFFFF          <1> 	jmp	badsys
  3941                              <1> 	;jmp	error
  3942                              <1> 	;;jmp 	sysret
  3943                              <1> 
  3944                              <1> 	; Original UNIX v1 'sysemt' routine
  3945                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3946                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3947                              <1> 			  ;/ put it in loc 8.,
  3948                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3949                              <1> 		       ; / trap address
  3950                              <1>         ;blo    1f / is the address a user core address?  
  3951                              <1> 		; / yes, go to 2f
  3952                              <1>         ;cmp    10,$ecore
  3953                              <1>         ;blo    2f
  3954                              <1> ;1:
  3955                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3956                              <1> 		    ; / instruction trap address for the system
  3957                              <1> ;2:
  3958                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3959                              <1> 
  3960                              <1> sysmdate: ; < change the modification time of a file >
  3961                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3962                              <1> 	;	(ECX input)
  3963                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3964                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3965                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3966                              <1> 	;
  3967                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3968                              <1> 	; file into core. The user is checked if he is the owner 
  3969                              <1> 	; or super user. If he is neither an error occurs.
  3970                              <1> 	; 'setimod' is then called to set the i-node modification
  3971                              <1> 	; byte and the modification time, but the modification time
  3972                              <1> 	; is overwritten by whatever get put on the stack during
  3973                              <1> 	; a 'systime' system call. This calls are restricted to
  3974                              <1> 	; the super user.		
  3975                              <1> 	;
  3976                              <1> 	; Calling sequence:
  3977                              <1> 	;	sysmdate; name
  3978                              <1> 	; Arguments:
  3979                              <1> 	;	name - points to the name of file
  3980                              <1> 	; Inputs: (arguments)
  3981                              <1> 	; Outputs: -
  3982                              <1> 	; ...............................................................
  3983                              <1> 	;				
  3984                              <1> 	; Retro UNIX 8086 v1 modification: 
  3985                              <1> 	;	 The user/application program puts address 
  3986                              <1> 	;	 of the file name in BX register 
  3987                              <1> 	;	 as 'sysmdate' system call argument.
  3988                              <1> 	;
  3989                              <1> ; / change the modification time of a file
  3990                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3991 00004024 891D[64700000]      <1>         mov	[u.namep], ebx
  3992                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3993 0000402A 890D[D06C0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3994 00004030 E897090000          <1> 	call	namei
  3995                              <1> 		; jsr r0,namei / get its i-number
  3996                              <1> 	;;jc	error       
  3997                              <1> 	;	; br error2 / no, such file
  3998                              <1> 	;jc	fnotfound ; file not found !
  3999                              <1> 	; 24/12/2021
  4000 00004035 7305                <1> 	jnc	short mdate_0
  4001 00004037 E99BFEFFFF          <1> 	jmp	fnotfound
  4002                              <1> mdate_0:
  4003 0000403C E89B110000          <1> 	call	iget
  4004                              <1> 		; jsr r0,iget / get i-node into core
  4005 00004041 A0[98700000]        <1> 	mov	al, [u.uid]
  4006 00004046 3A05[4B6D0000]      <1> 	cmp	al, [i.uid]
  4007                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  4008 0000404C 7413                <1> 	je	short mdate_1
  4009                              <1>         	; beq 1f / yes
  4010 0000404E 20C0                <1> 	and	al, al
  4011                              <1> 		; tstb u.uid / no, is user the super user
  4012                              <1> 	;jnz	error
  4013                              <1> 		; bne error2 / no, error
  4014 00004050 740F                <1> 	jz	short mdate_1
  4015 00004052 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4015 0000405A 0000                <1>
  4016                              <1> sysstty_err:	; 04/02/2022
  4017 0000405C E95EFAFFFF          <1> 	jmp	error
  4018                              <1> mdate_1: ;1:
  4019 00004061 E880120000          <1> 	call	setimod
  4020                              <1>         	; jsr r0,setimod / fill in modification data,
  4021                              <1> 		               ; / time etc.
  4022 00004066 BE[D06C0000]        <1> 	mov	esi, p_time
  4023 0000406B BF[626D0000]        <1> 	mov	edi, i.mtim
  4024 00004070 A5                  <1> 	movsd
  4025                              <1> 		; mov 4(sp),i.mtim / move present time to
  4026                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4027 00004071 E969FAFFFF          <1>         jmp	sysret
  4028                              <1> 		; br sysret2
  4029                              <1> 
  4030                              <1> 	; 04/02/2022
  4031                              <1> sysstty_err_s:
  4032 00004076 880D[4C700000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4033 0000407C EBDE                <1> 	jmp	short sysstty_err
  4034                              <1> 
  4035                              <1> sysstty: ; < set tty status and mode >
  4036                              <1> 	; 26/02/2022
  4037                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4038                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4039                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4040                              <1> 	; 17/11/2015
  4041                              <1> 	; 12/11/2015
  4042                              <1> 	; 29/10/2015
  4043                              <1> 	; 17/10/2015
  4044                              <1> 	; 13/10/2015
  4045                              <1> 	; 29/06/2015
  4046                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4047                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4048                              <1> 	;
  4049                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4050                              <1> 	; whose file descriptor is in (u.r0).
  4051                              <1> 	;
  4052                              <1> 	; Calling sequence:
  4053                              <1> 	;	sysstty; arg
  4054                              <1> 	; Arguments:
  4055                              <1> 	;	arg - address of 3 consequitive words that contain
  4056                              <1> 	;	      the source of status data	
  4057                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4058                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4059                              <1> 	; ...............................................................
  4060                              <1> 	;	
  4061                              <1> 	; Retro UNIX 8086 v1 modification: 
  4062                              <1> 	;	'sysstty' system call will set the tty
  4063                              <1> 	;	(clear keyboard buffer and set cursor position)
  4064                              <1> 	;	 in following manner:
  4065                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4066                              <1> 	;
  4067                              <1> 	; Inputs:
  4068                              <1> 	;	BX = 0 --> means
  4069                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4070                              <1> 	;	      set cursor position for console tty, only 
  4071                              <1> 	;	      CH will be ignored (char. will not be written)	
  4072                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4073                              <1> 	;	      set console tty for (current) process
  4074                              <1> 	;	      CL = tty number (0 to 9)
  4075                              <1> 	;	      (If CH = 0, character will not be written)			
  4076                              <1> 	;          If CH > 0 (CL < FFh)	
  4077                              <1> 	;             CL = tty number (0 to 9)
  4078                              <1> 	;	      CH = character will be written
  4079                              <1> 	;	        at requested cursor position (in DX)	
  4080                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4081                              <1>   	;		(only tty number 0 to 7) 
  4082                              <1> 	;          DL = communication parameters (for serial ports) 
  4083                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4084                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4085                              <1> 	;			or set cursor position	
  4086                              <1> 	;	   DH = 0FFh -> DL is not valid
  4087                              <1> 	;		do not set serial port parameters 
  4088                              <1> 	;		or do not set cursor position
  4089                              <1> 	;
  4090                              <1> 	;	BX > 0 --> points to name of tty
  4091                              <1> 	;    	   CH > 0 -->
  4092                              <1> 	;		CH = character will be written in current 
  4093                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4094                              <1> 	;	     	or character will be sent to serial port
  4095                              <1> 	;	     	(for tty number 8 or 9)
  4096                              <1> 	;		CL = color of the character if tty number < 8.
  4097                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4098                              <1> 	;		set mode (tty 8 to 9) or 
  4099                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4100                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4101                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4102                              <1> 	;		(DL is not valid)
  4103                              <1> 	;	   DL = communication parameters 
  4104                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4105                              <1> 	;
  4106                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4107                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4108                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4109                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4110                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4111                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4112                              <1> 	;
  4113                              <1> 	; Outputs:
  4114                              <1> 	;	cf = 0 -> OK
  4115                              <1> 	;	     AL = tty number (0 to 9)
  4116                              <1> 	;	     AH = line status if tty number is 8 or 9
  4117                              <1> 	;	     AH = process number (of the caller) 	
  4118                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4119                              <1> 	;	     AH = FFh if the tty is locked 
  4120                              <1> 	;		  (owned by another process)
  4121                              <1> 	;	        = process number (of the caller) 
  4122                              <1> 	;		  (if < FFh and tty number < 8)
  4123                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4124                              <1> 	;	     AH = line status if tty number is 8 or 9
  4125                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4126                              <1> 	;	
  4127                              <1> 
  4128                              <1> 	; 27/06/2015 (32 bit modifications)
  4129                              <1> 	; 14/01/2014
  4130 0000407E 31C0                <1> 	xor 	eax, eax
  4131 00004080 6648                <1> 	dec	ax ; 17/10/2015
  4132 00004082 A3[4C700000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4133                              <1> 	;;;
  4134                              <1> 	; 01/02/2022
  4135 00004087 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4136 00004089 39C2                <1> 	cmp	edx, eax
  4137                              <1> 	;cmp	dx, ax ; 0FFFFh
  4138 0000408B 7521                <1> 	jne	short sysstty_18
  4139                              <1> 	; clear video page
  4140                              <1> 	; (CH must be 0)
  4141 0000408D 08ED                <1> 	or	ch, ch
  4142 0000408F 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4143 00004091 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4144 00004094 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4145 00004096 20C9                <1> 	and	cl, cl
  4146 00004098 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4147 0000409A 0FB635[9B700000]    <1> 	movzx	esi, byte [u.uno]
  4148 000040A1 8A8E[A76D0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4149 000040A7 80F907              <1> 	cmp	cl, 7
  4150 000040AA 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4151                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4152 000040AC FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4153                              <1> sysstty_18:
  4154 000040AE FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4155                              <1> 	; cl = video page (tty) number		
  4156                              <1> 	;;;
  4157 000040B0 21DB                <1> 	and	ebx, ebx
  4158                              <1> 	;jnz	sysstty_6
  4159                              <1> 	; 01/02/2022
  4160 000040B2 7405                <1> 	jz	short sysstty_19
  4161 000040B4 E9C2000000          <1> 	jmp	sysstty_6
  4162                              <1> sysstty_19:
  4163                              <1> 	; set console tty
  4164                              <1> 	; 29/10/2015
  4165                              <1> 	; 17/01/2014 
  4166 000040B9 80F909              <1> 	cmp	cl, 9
  4167 000040BC 7613                <1> 	jna	short sysstty_0
  4168                              <1> 	; 17/11/2015
  4169 000040BE 80F9FF              <1> 	cmp	cl, 0FFh
  4170 000040C1 7202                <1> 	jb	short sysstty_13
  4171 000040C3 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4172                              <1> sysstty_13:
  4173 000040C5 8A1D[9B700000]      <1> 	mov	bl, [u.uno] ; process number
  4174 000040CB 8A8B[A76D0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4175                              <1> sysstty_0:
  4176                              <1> 	; 29/06/2015
  4177                              <1> 	;push	dx
  4178                              <1> 	;push	cx
  4179                              <1> 	; 01/02/2022
  4180 000040D1 52                  <1> 	push	edx
  4181 000040D2 51                  <1> 	push	ecx
  4182 000040D3 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4183 000040D5 88C8                <1> 	mov	al, cl
  4184 000040D7 A2[4C700000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4185 000040DC E8EF190000          <1> 	call	ottyp
  4186                              <1> 	; 01/02/2022
  4187 000040E1 59                  <1> 	pop	ecx
  4188 000040E2 5A                  <1> 	pop	edx
  4189                              <1> 	;pop	cx
  4190                              <1> 	;pop	dx
  4191                              <1> 	;
  4192 000040E3 7220                <1> 	jc	short sysstty_pd_err
  4193                              <1> 	;
  4194                              <1> 	; 26/02/2022 (Bug! BugFix)
  4195                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4196                              <1> 	;
  4197 000040E5 80F908              <1> 	cmp	cl, 8
  4198 000040E8 720C                <1> 	jb	short sysstty_2
  4199                              <1> 	;
  4200 000040EA 80FEFF              <1> 	cmp	dh, 0FFh
  4201 000040ED 7407                <1> 	je	short sysstty_2
  4202                              <1> 		; set communication parameters for serial ports
  4203                              <1> 
  4204                              <1> ; 01/02/2022
  4205                              <1> ;	; 29/10/2015
  4206                              <1> ;	mov	ah, dl ; communication parameters
  4207                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4208                              <1> ;		;			 THRE int + RDA int 
  4209                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4210                              <1> ;		;			 THRE int + RDA int 
  4211                              <1> ;	sub	al, al ; 0
  4212                              <1> ;	; 12/07/2014
  4213                              <1> ;	cmp	cl, 9
  4214                              <1> ;	jb	short sysstty_1
  4215                              <1> ;	inc	al
  4216                              <1> ;sysstty_1:
  4217                              <1> ;	; 01/02/2022
  4218                              <1> ;	push	ecx
  4219                              <1> ;	;push	cx
  4220                              <1> ;	; 29/06/2015	
  4221                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4222                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4223                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4224                              <1> ;	; 01/02/2022
  4225                              <1> ;	pop	ecx	
  4226                              <1> ;	;pop	cx
  4227                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4228                              <1> 
  4229                              <1> 	; 01/02/2022
  4230 000040EF E830010000          <1> 	call	sysstty_scp
  4231 000040F4 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4232                              <1> 
  4233                              <1> sysstty_2:
  4234                              <1> 	; 17/01/2014
  4235 000040F6 20ED                <1> 	and	ch, ch 	; set cursor position 
  4236                              <1> 			; or comm. parameters ONLY
  4237 000040F8 7527                <1> 	jnz	short sysstty_3
  4238                              <1> 	; 01/02/2022
  4239 000040FA 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4240 000040FE 7214                <1> 	jb	short sysstty_20
  4241                              <1> 	; clear screen (video page)
  4242 00004100 E93B010000          <1> 	jmp	sysstty_14
  4243                              <1> 
  4244                              <1> sysstty_pd_err: ; 29/06/2015
  4245                              <1> 	; 'permission denied !' error
  4246 00004105 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4246 0000410D 0000                <1>
  4247 0000410F E9ABF9FFFF          <1> 	jmp	error
  4248                              <1> 
  4249                              <1> sysstty_20:
  4250 00004114 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4251 0000411B 888B[A76D0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4252                              <1> sysstty_3:
  4253                              <1> 	; 16/01/2014
  4254 00004121 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4255                              <1> 	; 17/11/2015
  4256 00004123 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4257 00004125 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4258                              <1> 	;jna	sysstty_9
  4259                              <1> 	; 01/02/2022
  4260 00004127 7705                <1> 	ja	short sysstty_12
  4261 00004129 E9C5000000          <1> 	jmp	sysstty_9
  4262                              <1> 
  4263                              <1> sysstty_12:
  4264                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4265                              <1> 	; (Set specified serial port as console tty port)
  4266                              <1> 	; CH = character to be written
  4267                              <1> 	; 15/04/2014
  4268                              <1> 	; CH = 0 --> initialization only
  4269                              <1> 	; AL = character
  4270                              <1> 	; 26/06/2014
  4271 0000412E 880D[A0700000]      <1> 	mov	[u.ttyn], cl
  4272                              <1> 	; 12/07/2014
  4273 00004134 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4274                              <1> 	; 02/02/2022
  4275 00004136 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4276 00004138 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4277 0000413A FEC8                <1> 	dec	al  ; 1 -> 0	
  4278                              <1> 	;and	al, al
  4279 0000413C 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4280                              <1>  	; 04/07/2014
  4281 0000413E E8E81F0000          <1> 	call 	sndc
  4282                              <1> 	; 12/07/2014
  4283 00004143 EB0C                <1> 	jmp	short sysstty_5
  4284                              <1> 
  4285                              <1> sysstty_4:
  4286                              <1> 	; 12/07/2014
  4287                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4288 00004145 88E0                <1> 	mov	al, ah ; 29/06/2015
  4289 00004147 2C08                <1> 	sub	al, 8
  4290                              <1> 	; 27/06/2015
  4291 00004149 E824F4FFFF          <1> 	call	sp_status ; get serial port status
  4292                              <1> 	; AL = Line status, AH = Modem status
  4293                              <1> 	; 12/11/2015
  4294 0000414E 3C80                <1> 	cmp	al, 80h
  4295 00004150 F5                  <1> 	cmc
  4296                              <1> sysstty_5:
  4297 00004151 66A3[4D700000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4298                              <1> 		; EAX bits 16-23 = modem status	
  4299 00004157 9C                  <1> 	pushf
  4300 00004158 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4301 0000415A A0[A0700000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4302 0000415F E88F1A0000          <1> 	call	cttyp
  4303 00004164 9D                  <1> 	popf
  4304                              <1> 	;jnc	sysret ; time out error 
  4305                              <1> 	; 01/02/2022
  4306 00004165 7205                <1> 	jc	short sysstty_tmout_err
  4307 00004167 E973F9FFFF          <1> 	jmp	sysret
  4308                              <1> 
  4309                              <1> sysstty_tmout_err:
  4310 0000416C C705[A1700000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4310 00004174 0000                <1>
  4311 00004176 E944F9FFFF          <1> 	jmp	error
  4312                              <1> 
  4313                              <1> sysstty_6:
  4314                              <1> 	;push	dx
  4315                              <1> 	;push	cx
  4316                              <1> 	; 01/02/2022
  4317 0000417B 52                  <1> 	push	edx
  4318 0000417C 51                  <1> 	push	ecx
  4319 0000417D 891D[64700000]      <1> 	mov	[u.namep], ebx
  4320 00004183 E844080000          <1> 	call	namei
  4321                              <1> 	; 01/02/2022
  4322 00004188 59                  <1> 	pop	ecx
  4323 00004189 5A                  <1> 	pop	edx
  4324                              <1> 	;pop	cx
  4325                              <1> 	;pop	dx
  4326 0000418A 7258                <1> 	jc	short sysstty_inv_dn
  4327                              <1> 	;
  4328 0000418C 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4329 00004190 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4330                              <1> 	;
  4331 00004192 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4332                              <1> 		       ; /dev/COM1, /dev/COM2
  4333 00004194 7204                <1> 	jb	short sysstty_7
  4334 00004196 2C0A                <1> 	sub	al, 10
  4335 00004198 EB11                <1> 	jmp	short sysstty_8
  4336                              <1> 
  4337                              <1> sysstty_7:
  4338 0000419A 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4339 0000419C 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4340 0000419E 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4341 000041A5 8A83[A76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4342                              <1> sysstty_8:
  4343                              <1> 	; 26/02/2022
  4344                              <1> 	; (ebx < 256)	
  4345 000041AB A2[4C700000]        <1> 	mov	[u.r0], al
  4346                              <1> 	; 01/02/2022
  4347                              <1> 	;push	dx
  4348                              <1> 	;push	ax
  4349                              <1> 	;push	cx
  4350 000041B0 52                  <1> 	push	edx
  4351 000041B1 50                  <1> 	push	eax
  4352 000041B2 51                  <1> 	push	ecx	
  4353 000041B3 E818190000          <1> 	call	ottyp
  4354 000041B8 59                  <1> 	pop	ecx
  4355 000041B9 58                  <1> 	pop	eax
  4356 000041BA 5A                  <1> 	pop	edx
  4357                              <1> 	;pop	cx
  4358                              <1> 	;pop	ax
  4359                              <1> 	;pop	dx
  4360                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4361                              <1> 	; 01/02/2022
  4362 000041BB 7305                <1> 	jnc	short sysstty_21
  4363 000041BD E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4364                              <1> sysstty_21:
  4365                              <1> 	; 29/10/2015
  4366 000041C2 86E9                <1> 	xchg 	ch, cl
  4367                              <1> 		; cl = character, ch = color code
  4368 000041C4 86C1                <1> 	xchg	al, cl
  4369                              <1> 		; al = character, cl = tty number
  4370 000041C6 80F907              <1> 	cmp	cl, 7
  4371                              <1> 	;ja	sysstty_12
  4372                              <1> 	; 01/02/2022
  4373 000041C9 7628                <1> 	jna	short sysstty_16
  4374                              <1> ;;
  4375 000041CB 80FEFF              <1> 	cmp	dh, 0FFh
  4376 000041CE 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4377                              <1> 
  4378                              <1> ; 01/02/2022
  4379                              <1> ;	; 29/10/2015
  4380                              <1> ;	mov	ah, dl ; communication parameters
  4381                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4382                              <1> ;		;			 THRE int + RDA int 
  4383                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4384                              <1> ;		;			 THRE int + RDA int 
  4385                              <1> ;	sub	al, al ; 0
  4386                              <1> ;	; 12/07/2014
  4387                              <1> ;	cmp	cl, 9
  4388                              <1> ;	jb	short sysstty_1
  4389                              <1> ;	inc	al
  4390                              <1> ;sysstty_1:
  4391                              <1> ;	; 01/02/2022
  4392                              <1> ;	push	ecx
  4393                              <1> ;	;push	cx
  4394                              <1> ;	; 29/06/2015	
  4395                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4396                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4397                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4398                              <1> ;	; 01/02/2022
  4399                              <1> ;	pop	ecx	
  4400                              <1> ;	;pop	cx
  4401                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4402                              <1> 
  4403                              <1> 	; 02/02/2022
  4404 000041D0 88C5                <1> 	mov	ch, al ; save char
  4405                              <1> 	; 01/02/2022
  4406 000041D2 E84D000000          <1> 	call	sysstty_scp
  4407 000041D7 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4408                              <1> 	; 02/02/2022
  4409 000041D9 88E8                <1> 	mov	al, ch ; restore char
  4410                              <1> sysstty_22:
  4411                              <1> 	; 01/02/2022
  4412 000041DB 08ED                <1> 	or	ch, ch
  4413 000041DD 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4414                              <1> 	; send char to (serial port) terminal
  4415                              <1> 	; al = character
  4416                              <1> 	; cl = tty number (8 or 9)
  4417 000041DF E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4418                              <1> 
  4419                              <1> sysstty_inv_dn: 
  4420                              <1> 	; 27/06/2015
  4421                              <1> 	; Invalid device name (not a tty) ! error
  4422                              <1> 	; (Device is not a tty or device name not found)
  4423 000041E4 C705[A1700000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4423 000041EC 0000                <1>
  4424 000041EE E9CCF8FFFF          <1> 	jmp	error 
  4425                              <1> 
  4426                              <1> sysstty_16:
  4427                              <1> 	; 26/02/2022
  4428                              <1> 	; 16/01/2014
  4429                              <1> 	;xor	bh, bh
  4430                              <1> 	; 02/02/2022
  4431                              <1> sysstty_9: 	; tty 0 to tty 7
  4432                              <1> 	; al = character
  4433                              <1> 	; ch = color/attribute ; 01/02/2022
  4434                              <1> 	;
  4435                              <1> 	; 26/02/2022 (BugFix)
  4436                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4437 000041F3 29DB                <1> 	sub	ebx, ebx ; *
  4438 000041F5 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4439 000041F8 740B                <1> 	je	short sysstty_10
  4440                              <1> 	; 02/02/2022
  4441 000041FA 51                  <1> 	push	ecx
  4442 000041FB 50                  <1> 	push	eax
  4443                              <1> 	;push	cx
  4444                              <1> 	;push	ax	
  4445                              <1> 	;movzx	ebx, cl
  4446 000041FC 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4447 000041FE E8C8D2FFFF          <1> 	call	set_cpos
  4448                              <1> 	;pop	ax
  4449                              <1> 	;pop	cx
  4450                              <1> 	; 02/02/2022
  4451 00004203 58                  <1> 	pop	eax
  4452 00004204 59                  <1> 	pop	ecx
  4453                              <1> sysstty_10: 
  4454                              <1> 	; 29/10/2015
  4455 00004205 08C0                <1> 	or	al, al ; character
  4456 00004207 740D                <1> 	jz      short sysstty_11 ; al = 0
  4457                              <1> 	; 17/11/2015
  4458 00004209 3CFF                <1> 	cmp	al, 0FFh
  4459 0000420B 7309                <1> 	jnb	short sysstty_11
  4460                              <1> 		; ch > 0 and ch < FFh
  4461                              <1> 	; write a character at current cursor position
  4462 0000420D 88EC                <1> 	mov	ah, ch ; color/attribute
  4463                              <1> 	; 12/07/2014
  4464                              <1> 	;push	cx
  4465                              <1> 	; 02/02/2022
  4466 0000420F 51                  <1> 	push	ecx
  4467 00004210 E89ED3FFFF          <1> 	call	write_c_current
  4468                              <1> 	;pop	cx
  4469                              <1> 	; 02/02/2022
  4470 00004215 59                  <1> 	pop	ecx
  4471                              <1> sysstty_11:
  4472                              <1> 	; 14/01/2014
  4473 00004216 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4474                              <1> 	; 18/01/2014
  4475                              <1> 	;movzx	eax, cl ; 27/06/2015
  4476 00004218 88C8                <1> 	mov	al, cl
  4477 0000421A E8D4190000          <1> 	call	cttyp
  4478 0000421F E9BBF8FFFF          <1> 	jmp	sysret
  4479                              <1> 
  4480                              <1> sysstty_scp:
  4481                              <1> 	; 02/02/2022
  4482                              <1> 	; set communication parameters (for COM1 or COM2)
  4483                              <1> 	; 01/02/2022
  4484                              <1> 	;
  4485                              <1> 	; 29/10/2015
  4486 00004224 88D4                <1> 	mov	ah, dl ; communication parameters
  4487                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4488                              <1> 		;			 THRE int + RDA int 
  4489                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4490                              <1> 		;			 THRE int + RDA int 
  4491 00004226 28C0                <1> 	sub	al, al ; 0
  4492                              <1> 	; 12/07/2014
  4493 00004228 80F909              <1> 	cmp	cl, 9
  4494 0000422B 7202                <1> 	jb	short sysstty_1
  4495 0000422D FEC0                <1> 	inc	al
  4496                              <1> sysstty_1:
  4497                              <1> 	; 02/02/2022
  4498 0000422F 52                  <1> 	push	edx
  4499                              <1> 	; 01/02/2022
  4500 00004230 51                  <1> 	push	ecx
  4501                              <1> 	;push	cx
  4502                              <1> 	; 29/06/2015	
  4503 00004231 E844F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4504 00004236 66890D[4D700000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4505                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4506                              <1> 	; 01/02/2022
  4507 0000423D 59                  <1> 	pop	ecx	
  4508                              <1> 	;pop	cx
  4509 0000423E 5A                  <1> 	pop	edx ; 02/02/2022
  4510                              <1> 	; 01/02/2022
  4511                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4512 0000423F C3                  <1> 	retn
  4513                              <1> 
  4514                              <1> sysstty_14:
  4515                              <1> 	; 26/02/2022
  4516                              <1> 	; 02/02/2022
  4517                              <1> 	; ch = 0
  4518                              <1> 	; cl = video page
  4519                              <1> 	;
  4520                              <1> 	; dx = 0FFFFh
  4521                              <1> 	; clear screen (video page)
  4522                              <1> 	;
  4523                              <1> 
  4524                              <1> 	; 02/02/2022
  4525                              <1> 	; clear screen
  4526                              <1> 	;
  4527                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4528                              <1> 	; clear video page
  4529                              <1> 
  4530                              <1> 	; 26/02/2022
  4531 00004240 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4532                              <1> 
  4533                              <1> 	; clear video page
  4534 00004242 E810000000          <1> 	call	wttyc ; 26/02/2022
  4535                              <1> 
  4536                              <1> 	; 26/02/2022
  4537 00004247 88D8                <1> 	mov	al, bl
  4538 00004249 8A25[9B700000]      <1> 	mov	ah, [u.uno]
  4539 0000424F 66A3[4C700000]      <1> 	mov	[u.r0], ax
  4540 00004255 EBBF                <1> 	jmp	short sysstty_11
  4541                              <1> 
  4542                              <1> vp_clr:	; 27/02/2022
  4543                              <1> wttyc:
  4544                              <1> 	; 23/02/2022
  4545                              <1> 	; (clear video page)
  4546                              <1> 	; INPUT:
  4547                              <1> 	;  bl = video page (0 to 7)
  4548                              <1> 	;
  4549                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4550                              <1> 
  4551                              <1> 	;xor	dx, dx ; column 0, row 0
  4552                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4553                              <1> 	;
  4554                              <1> ;	movzx	ebx, cl
  4555                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4556                              <1> 
  4557                              <1> ;	shl 	bl, 1 
  4558                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4559                              <1> ;		; AL = lock value (0 or process number)
  4560                              <1> ;	or	al, al
  4561                              <1> ;	jz	short @f
  4562                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4563                              <1> ;	jne	short sysstty_15
  4564                              <1> ;		; only the owner can clear its video page
  4565                              <1> ;	xor	al, al ; 0
  4566                              <1> ;@@:
  4567                              <1> ;	;mov	bl, cl		
  4568                              <1> ;	shr	bl, 1 
  4569                              <1> 
  4570 00004257 30C0                <1> 	xor	al, al	; 0
  4571 00004259 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4572                              <1> 
  4573                              <1> 	; scroll_up input:
  4574                              <1> 	;
  4575                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4576                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4577                              <1> 	; ah = attribute to be used on blanked line
  4578                              <1> 	; bl = video page number (0 to 7)
  4579                              <1> 
  4580 0000425B E8F1D2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4581                              <1> 
  4582                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4583                              <1> 
  4584                              <1> 	; bl = video page number (0 to 7)
  4585                              <1> 	;xor	dx, dx ; column 0, row 0
  4586                              <1> 	; 02/02/2022
  4587 00004260 31D2                <1> 	xor	edx, edx
  4588                              <1> 	; 26/02/2022
  4589                              <1> 	;call	set_cpos
  4590                              <1> 	;retn
  4591 00004262 E964D2FFFF          <1> 	jmp	set_cpos
  4592                              <1> 
  4593                              <1> 	;mov	al, bl
  4594                              <1> 	;mov	ah, [u.uno]
  4595                              <1> 	;mov	[u.r0], ax
  4596                              <1> 	;jmp	short sysstty_11
  4597                              <1> 
  4598                              <1> ;sysstty_15:
  4599                              <1> ;	; 30/01/2022
  4600                              <1> ;	; permission (denied) error
  4601                              <1> ;	;xor	dl, dl ; sysstty call sign
  4602                              <1> ;	mov	al, cl
  4603                              <1> ;	sub	ah, ah ; 0
  4604                              <1> ;	call	cttyp
  4605                              <1> ;	jmp	error
  4606                              <1> 
  4607                              <1> ; Original UNIX v1 'sysstty' routine:
  4608                              <1> ; gtty:
  4609                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4610                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4611                              <1> 	; 		/ r2 has source
  4612                              <1>         ;mov    r2,-(sp)
  4613                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4614                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4615                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4616                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4617                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4618                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4619                              <1>         ;       br .+4 / list empty, skip branch
  4620                              <1>         ;br     1b / get another character until list is empty
  4621                              <1>         ;mov    0b,r1 / move cc offset to r1
  4622                              <1>         ;inc    r1 / bump it for output clist
  4623                              <1>         ;tstb   cc(r1) / is it 0
  4624                              <1>         ;beq    1f / yes, no characters to output
  4625                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4626                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4627                              <1>         ;br     1b / try to calm it down again
  4628                              <1> ;1:
  4629                              <1>         ;mov    (sp)+,r1
  4630                              <1>         ;mov    (sp)+,r2 / restore registers
  4631                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4632                              <1>         ;beq    1f / if 0, 1f
  4633                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4634                              <1>         ;                   / control status register
  4635                              <1> ;1:
  4636                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4637                              <1>         ;beq    1f / if 0 1f
  4638                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4639                              <1> 	;		    / control status reg
  4640                              <1> ;1:
  4641                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4642                              <1>         ;jmp     sysret2 / return to user
  4643                              <1> 
  4644                              <1> sysgtty: ; < get tty status >
  4645                              <1> 	; 26/02/2022
  4646                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4647                              <1> 	;	    ((32 bit reg push/pop))
  4648                              <1> 	; 23/11/2015
  4649                              <1> 	; 29/10/2015
  4650                              <1> 	; 17/10/2015
  4651                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4652                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4653                              <1> 	;
  4654                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4655                              <1> 	; It stores in the three words addressed by it's argument
  4656                              <1> 	; the status of the typewriter whose file descriptor
  4657                              <1> 	; in (u.r0).
  4658                              <1> 	;
  4659                              <1> 	; Calling sequence:
  4660                              <1> 	;	sysgtty; arg
  4661                              <1> 	; Arguments:
  4662                              <1> 	;	arg - address of 3 words destination of the status
  4663                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4664                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4665                              <1> 	; ...............................................................
  4666                              <1> 	;	
  4667                              <1> 	; Retro UNIX 8086 v1 modification: 
  4668                              <1> 	;	'sysgtty' system call will return status of tty
  4669                              <1> 	;	(keyboard, serial port and video page status)
  4670                              <1> 	;	 in following manner:
  4671                              <1> 	;
  4672                              <1> 	; Inputs:
  4673                              <1> 	;	BX = 0 --> means 
  4674                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4675                              <1> 	;	                 for (current) process
  4676                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4677                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4678                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4679                              <1> 	;	     CH > 0 -->	tty number + 1
  4680                              <1> 	;
  4681                              <1> 	;	BX > 0 --> points to name of tty
  4682                              <1> 	;	     CL = 0 --> return keyboard status
  4683                              <1> 	;	     CL = 1 --> return video page status
  4684                              <1> 	;	     CH = undefined		 
  4685                              <1> 	;
  4686                              <1> 	; Outputs:
  4687                              <1> 	;	cf = 0 ->
  4688                              <1> 	;
  4689                              <1> 	;	     AL = tty number from 0 to 9
  4690                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4691                              <1> 	;	     AH = 0 if the tty is free/unused
  4692                              <1> 	;	     AH = the process number of the caller 
  4693                              <1>  	;	     AH = FFh if the tty is locked by another process
  4694                              <1> 	;
  4695                              <1> 	;	  (if calling is for serial port status)
  4696                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4697                              <1> 	;		  (BH = modem status, BL = Line status)
  4698                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4699                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4700                              <1> 	;
  4701                              <1> 	;	  (if calling is for keyboard status)
  4702                              <1> 	;	     BX = current character in tty/keyboard buffer
  4703                              <1> 	;		  (BH = scan code, BL = ascii code)
  4704                              <1> 	;		  (BX=0 if there is not a waiting character)
  4705                              <1> 	;	     CX  is undefined
  4706                              <1> 	;
  4707                              <1> 	;	  (if calling is for video page status)	
  4708                              <1> 	;	     BX = cursor position on the video page
  4709                              <1> 	;		  if tty number < 8
  4710                              <1> 	;		  (BH = row, BL = column)
  4711                              <1> 	;	     CX = current character (in cursor position)
  4712                              <1> 	;		  on the video page of the tty 
  4713                              <1> 	;		  if tty number < 8
  4714                              <1> 	;		  (CH = color, CL = character)
  4715                              <1> 	;	
  4716                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4717                              <1> 	;
  4718                              <1> 	;	     AH = FFh if the caller is not owner of
  4719                              <1> 	;		  specified tty or console tty
  4720                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4721                              <1> 	;	     BX, CX are undefined if cf = 1
  4722                              <1> 	;
  4723                              <1> 	;	  (If tty number is 8 or 9)
  4724                              <1> 	;	     AL = tty number 
  4725                              <1> 	;	     AH = the process number of the caller 
  4726                              <1> 	;	     BX = serial port status
  4727                              <1> 	;  		 (BH = modem status, BL = Line status)
  4728                              <1> 	;	     CX = 0
  4729                              <1> 	;
  4730                              <1> 		
  4731                              <1> gtty:   ; get (requested) tty number
  4732                              <1> 	; 26/02/2022
  4733                              <1> 	; 17/10/2015
  4734                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4735                              <1> 	; 30/05/2013 - 12/07/2014
  4736                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4737                              <1> 	;
  4738                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4739                              <1> 	;
  4740                              <1> 	; 28/06/2015 (32 bit modifications)
  4741                              <1> 	; 16/01/2014
  4742 00004267 31C0                <1> 	xor 	eax, eax
  4743 00004269 6648                <1> 	dec	ax ; 17/10/2015
  4744 0000426B A3[4C700000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4745 00004270 80F901              <1> 	cmp	cl, 1
  4746 00004273 760F                <1> 	jna	short sysgtty_0
  4747                              <1> sysgtty_invp:
  4748                              <1> 	; 28/06/2015
  4749 00004275 C705[A1700000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4749 0000427D 0000                <1>
  4750 0000427F E93BF8FFFF          <1> 	jmp	error
  4751                              <1> sysgtty_0:	
  4752 00004284 21DB                <1> 	and	ebx, ebx
  4753 00004286 742E                <1> 	jz	short sysgtty_1
  4754                              <1> 	;
  4755 00004288 891D[64700000]      <1> 	mov	[u.namep], ebx
  4756                              <1> 	;push	cx ; 23/11/2015
  4757 0000428E 51                  <1> 	push	ecx ; 24/12/2021
  4758 0000428F E838070000          <1> 	call	namei
  4759 00004294 59                  <1> 	pop	ecx
  4760                              <1> 	;pop	cx ; 23/11/2015
  4761 00004295 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4762                              <1> 	;
  4763 00004297 6683F801            <1> 	cmp	ax, 1
  4764 0000429B 7622                <1> 	jna	short sysgtty_2
  4765                              <1> 	; 26/02/2022
  4766 0000429D 20E4                <1> 	and	ah, ah
  4767 0000429F 7506                <1> 	jnz	short sysgtty_inv_dn
  4768                              <1> 	;sub	ax, 10
  4769 000042A1 2C0A                <1> 	sub	al, 10
  4770 000042A3 3C09                <1> 	cmp	al, 9
  4771                              <1> 	;cmp	ax, 9
  4772                              <1> 	;ja	short sysgtty_inv_dn
  4773                              <1> 	;mov	ch, al
  4774                              <1> 	;jmp	short sysgtty_4
  4775                              <1> 	; 23/11/2015
  4776 000042A5 7629                <1> 	jna	short sysgtty_4
  4777                              <1> sysgtty_inv_dn: 
  4778                              <1> 	; 28/06/2015
  4779                              <1> 	; Invalid device name (not a tty) ! error
  4780                              <1> 	; (Device is not a tty or device name not found)
  4781 000042A7 C705[A1700000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4781 000042AF 0000                <1>
  4782 000042B1 E909F8FFFF          <1> 	jmp	error 
  4783                              <1> sysgtty_1:
  4784                              <1> 	; 16/01/2014
  4785 000042B6 80FD0A              <1> 	cmp	ch, 10
  4786 000042B9 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4787 000042BB FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4788 000042BD 790F                <1> 	jns	short sysgtty_3 ; not negative
  4789                              <1> 	;
  4790                              <1> sysgtty_2:
  4791                              <1> 	; get tty number of console tty
  4792 000042BF 8A25[9B700000]      <1> 	mov	ah, [u.uno]
  4793                              <1>  	; 28/06/2015
  4794 000042C5 0FB6DC              <1> 	movzx 	ebx, ah
  4795 000042C8 8AAB[A76D0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4796                              <1> sysgtty_3:
  4797 000042CE 88E8                <1> 	mov	al, ch
  4798                              <1> sysgtty_4:
  4799 000042D0 A2[4C700000]        <1> 	mov	[u.r0], al
  4800                              <1>  	; 28/06/2015
  4801                              <1> 	;cmp	al, 9
  4802                              <1> 	;ja	short sysgtty_invp
  4803 000042D5 8B2D[48700000]      <1> 	mov	ebp, [u.usp]
  4804                              <1> 	; 23/11/2015
  4805 000042DB 20C9                <1> 	and	cl, cl
  4806 000042DD 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4807 000042DF 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4808 000042E1 722E                <1> 	jb	short sysgtty_6 ; video page status
  4809                              <1> 	; serial port status
  4810                              <1> 	; 12/07/2014
  4811                              <1> 	;mov	dx, 0
  4812                              <1> 	;je	short sysgtty_5
  4813                              <1> 	;inc	dl
  4814                              <1> ;sysgtty_5:
  4815                              <1> 	; 28/06/2015
  4816 000042E3 2C08                <1> 	sub	al, 8
  4817 000042E5 E888F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4818                              <1> 	; AL = Line status, AH = Modem status
  4819 000042EA 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4820 000042EE 8A25[9B700000]      <1> 	mov	ah, [u.uno]
  4821 000042F4 8825[4D700000]      <1>         mov     [u.r0+1], ah
  4822                              <1> 	; 24/12/2021
  4823 000042FA 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4824                              <1> 				; (in ECX)
  4825 00004300 A880                <1> 	test	al, 80h
  4826 00004302 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4827 00004304 A801                <1> 	test	al, 1
  4828                              <1> 	;jz	sysret
  4829 00004306 7404                <1> 	jz	short sysgtty_10
  4830 00004308 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4831                              <1> sysgtty_10:
  4832 0000430C E9CEF7FFFF          <1> 	jmp	sysret
  4833                              <1> sysgtty_6:
  4834 00004311 A2[A0700000]        <1> 	mov	[u.ttyn], al ; tty number
  4835                              <1> 	;movzx	ebx, al
  4836 00004316 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4837 00004318 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4838                              <1> 	; 22/04/2014 - 29/06/2015
  4839 0000431A 81C3[D46C0000]      <1>         add     ebx, ttyl
  4840 00004320 8A23                <1>  	mov	ah, [ebx]
  4841 00004322 3A25[9B700000]      <1> 	cmp	ah, [u.uno]
  4842 00004328 7404                <1> 	je	short sysgtty_7
  4843 0000432A 20E4                <1> 	and	ah, ah
  4844                              <1> 	;jz	short sysgtty_7
  4845 0000432C 7506                <1> 	jnz	short sysgtty_8
  4846                              <1> 	;mov	ah, 0FFh
  4847                              <1> sysgtty_7:
  4848 0000432E 8825[4D700000]      <1>         mov     [u.r0+1], ah
  4849                              <1> sysgtty_8:
  4850 00004334 08C9                <1> 	or	cl, cl
  4851 00004336 7510                <1> 	jnz	short sysgtty_9
  4852 00004338 B001                <1> 	mov	al, 1  ; test a key is available
  4853 0000433A E86F1D0000          <1> 	call	getc
  4854 0000433F 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4855 00004343 E997F7FFFF          <1> 	jmp	sysret
  4856                              <1> sysgtty_9:
  4857 00004348 8A1D[A0700000]      <1> 	mov	bl, [u.ttyn]
  4858                              <1> 	; bl = video page number
  4859 0000434E E8CC1E0000          <1> 	call 	get_cpos
  4860                              <1> 	; dx = cursor position
  4861 00004353 66895510            <1> 	mov	[ebp+16], dx ; bx
  4862                              <1> 	;mov	bl, [u.ttyn]
  4863                              <1> 	; bl = video page number
  4864 00004357 E8D41E0000          <1> 	call	read_ac_current
  4865                              <1> 	; ax = character and attribute/color
  4866 0000435C 66894518            <1> 	mov	[ebp+24], ax ; cx
  4867 00004360 E97AF7FFFF          <1> 	jmp	sysret
  4868                              <1> sysgtty_dnr_err:
  4869                              <1> 	; 'device not responding !' error	
  4870                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4871 00004365 C705[A1700000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4871 0000436D 0000                <1>
  4872 0000436F E94BF7FFFF          <1> 	jmp	error	
  4873                              <1> 
  4874                              <1> ; Original UNIX v1 'sysgtty' routine:
  4875                              <1> ; sysgtty:
  4876                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4877                              <1> 	;	       / r2 has destination
  4878                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4879                              <1> 	;                     / in 1st word of dest
  4880                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4881                              <1> 	;                     / in 2nd word of dest
  4882                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4883                              <1>         ;jmp    sysret2 / return to user
  4884                              <1> 	
  4885                              <1> ; Original UNIX v1 'gtty' routine:
  4886                              <1> ; gtty:
  4887                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4888                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4889                              <1>         ;jsr    r0,getf / get the i-number of the file
  4890                              <1>         ;tst    r1 / is it open for reading
  4891                              <1>         ;bgt    1f / yes
  4892                              <1>         ;neg    r1 / no, i-number is negative, 
  4893                              <1> 	;          / so make it positive
  4894                              <1> ;1:
  4895                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4896                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4897                              <1>         ;bhis   error9 / no, error
  4898                              <1>         ;asl    r1 / 0%2
  4899                              <1>         ;asl    r1 / 0%4 / yes
  4900                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4901                              <1> 	;	       ; / tty block
  4902                              <1>         ;mov    u.off,r2 / put argument in r2
  4903                              <1>         ;rts    r0 / return
  2103                                  %include 'u2.s'        ; 11/05/2015
  2104                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS2.INC
  2105                              <1> ; Last Modification: 15/05/2022
  2106                              <1> ; ----------------------------------------------------------------------------
  2107                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2108                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2109                              <1> ;
  2110                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2111                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2112                              <1> ; <Bell Laboratories (17/3/1972)>
  2113                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2114                              <1> ;
  2115                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2116                              <1> ;
  2117                              <1> ; ****************************************************************************
  2118                              <1> 
  2119                              <1> syslink:
  2120                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2121                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2122                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2123                              <1> 	;
  2124                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2125                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2126                              <1> 	; given to the entry that will go in the current directory.
  2127                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2128                              <1> 	; in the name 2 entry of current directory is the same
  2129                              <1> 	; i-number for the name 1 file.
  2130                              <1> 	;
  2131                              <1> 	; Calling sequence:
  2132                              <1> 	;	syslink; name 1; name 2
  2133                              <1> 	; Arguments:
  2134                              <1> 	;	name 1 - file name to which link will be created.
  2135                              <1> 	;	name 2 - name of entry in current directory that
  2136                              <1> 	;		 links to name 1.
  2137                              <1> 	; Inputs: -
  2138                              <1> 	; Outputs: -
  2139                              <1> 	; ...............................................................
  2140                              <1> 	;	
  2141                              <1> 	; Retro UNIX 8086 v1 modification: 
  2142                              <1> 	;       'syslink' system call has two arguments; so,
  2143                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2144                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2145                              <1> 	;
  2146                              <1> 		; / name1, name2
  2147                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2148 00004374 891D[64700000]      <1> 	mov	[u.namep], ebx
  2149 0000437A 51                  <1> 	push	ecx
  2150 0000437B E84C060000          <1> 	call	namei
  2151                              <1> 		; jsr r0,namei / find the i-number associated with
  2152                              <1> 			     ; / the 1st path name
  2153                              <1>      	;;and	ax, ax
  2154                              <1> 	;;jz	error ; File not found
  2155                              <1> 	;jc	error 
  2156                              <1> 		; br error9 / cannot be found
  2157 00004380 730F                <1> 	jnc	short syslink0
  2158                              <1> 	;pop 	ecx
  2159                              <1> 	; 'file not found !' error
  2160 00004382 C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2160 0000438A 0000                <1>
  2161 0000438C E92EF7FFFF          <1> 	jmp	error
  2162                              <1> syslink0:
  2163 00004391 E8460E0000          <1> 	call	iget
  2164                              <1> 		; jsr r0,iget / get the i-node into core
  2165 00004396 8F05[64700000]      <1> 	pop	dword [u.namep] ; ecx
  2166                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2167                              <1> 	; 24/12/2021
  2168 0000439C 50                  <1> 	push	eax ; *
  2169                              <1> 	;push	ax
  2170                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2171                              <1> 			    ; / (a link to this file is to be created)
  2172                              <1> 	; 24/12/2021
  2173 0000439D 8A0D[2F700000]      <1> 	mov	cl, [cdev]
  2174 000043A3 51                  <1> 	push	ecx ; **
  2175                              <1> 	;push	word [cdev]
  2176                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2177 000043A4 E852000000          <1> 	call	isdir
  2178                              <1> 		; jsr r0,isdir / is it a directory
  2179 000043A9 E81E060000          <1> 	call	namei
  2180                              <1> 		; jsr r0,namei / no, get i-number of name2
  2181                              <1> 	;jnc	error
  2182                              <1> 		; br .+4   / not found 
  2183                              <1> 			 ; / so r1 = i-number of current directory
  2184                              <1> 			 ; / ii = i-number of current directory
  2185                              <1> 		; br error9 / file already exists., error
  2186 000043AE 720F                <1> 	jc	short syslink1
  2187                              <1> 	; pop eax ; 24/12/2021
  2188                              <1> 	; pop eax
  2189                              <1> 	; 'file exists !' error
  2190 000043B0 C705[A1700000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2190 000043B8 0000                <1>
  2191 000043BA E900F7FFFF          <1> 	jmp	error
  2192                              <1> syslink1:
  2193                              <1> 	;pop	cx
  2194                              <1> 	; 24/12/2021
  2195 000043BF 59                  <1> 	pop	ecx ; **
  2196                              <1> 	;cmp	cx, [cdev]
  2197 000043C0 3A0D[2F700000]      <1> 	cmp	cl, [cdev]
  2198                              <1> 	;jne	error
  2199                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2200                              <1> 			       ; / end of current directory
  2201                              <1> 	        ; bne error9
  2202 000043C6 740F                <1> 	je	short syslink2
  2203                              <1> 	; 'not same drive !' error
  2204 000043C8 C705[A1700000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2204 000043D0 0000                <1>
  2205 000043D2 E9E8F6FFFF          <1> 	jmp	error
  2206                              <1> syslink2:
  2207                              <1> 	;pop	eax ; 24/12/2021
  2208                              <1> 	;push	eax
  2209                              <1> 	; 24/12/2021
  2210 000043D7 8B0424              <1> 	mov	eax, [esp] ; *
  2211 000043DA 66A3[7E700000]      <1> 	mov	[u.dirbuf], ax
  2212                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2213 000043E0 E89E000000          <1> 	call	mkdir
  2214                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2215                              <1> 		 	     ; / in current directory
  2216                              <1> 	; 24/12/2021
  2217 000043E5 58                  <1> 	pop	eax ; *
  2218                              <1> 	;pop	ax
  2219                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2220 000043E6 E8F10D0000          <1> 	call	iget
  2221                              <1> 		; jsr r0,iget / get i-node into core
  2222 000043EB FE05[4A6D0000]      <1> 	inc	byte [i.nlks]
  2223                              <1> 		; incb i.nlks / add 1 to its number of links
  2224 000043F1 E8F00E0000          <1> 	call	setimod
  2225                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2226 000043F6 E9E4F6FFFF          <1> 	jmp	sysret
  2227                              <1> 
  2228                              <1> isdir:
  2229                              <1> 	; 03/02/2022
  2230                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2231                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2232                              <1> 	;
  2233                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2234                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2235                              <1> 	;  called by syslink and sysunlink to make sure directories
  2236                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2237                              <1> 	; 'isdir' does not bother checking. The current i-node
  2238                              <1> 	;  is not disturbed.			
  2239                              <1> 	;		
  2240                              <1> 	; INPUTS ->
  2241                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2242                              <1> 	;    u.uid - user id
  2243                              <1> 	; OUTPUTS ->
  2244                              <1> 	;    r1 - contains current i-number upon exit
  2245                              <1> 	;    	 (current i-node back in core) 
  2246                              <1> 	;	
  2247                              <1> 	; ((AX = R1))
  2248                              <1> 	;
  2249                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2250                              <1> 	;
  2251                              <1> 
  2252                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2253                              <1> 	; / there is an error unless super user made the call
  2254                              <1> 	
  2255 000043FB 803D[98700000]00    <1> 	cmp	byte [u.uid], 0 
  2256                              <1> 		; tstb u.uid / super user
  2257 00004402 762B                <1> 	jna	short isdir1
  2258                              <1> 		; beq 1f / yes, don't care
  2259 00004404 66FF35[2C700000]    <1> 	push	word [ii]
  2260                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2261 0000440B E8CC0D0000          <1> 	call	iget
  2262                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2263                              <1> 	; 03/02/2022
  2264 00004410 F605[496D0000]40    <1> 	test	byte [i.flgs+1], 40h
  2265                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2266                              <1> 		; bit $40000,i.flgs / is it a directory
  2267                              <1> 	;jnz	error
  2268                              <1> 		; bne error9 / yes, error
  2269 00004417 740F                <1> 	jz	short isdir0
  2270 00004419 C705[A1700000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2270 00004421 0000                <1>
  2271                              <1> 				; 'permission denied !' error
  2272                              <1> 	; pop	ax
  2273 00004423 E997F6FFFF          <1> 	jmp	error	
  2274                              <1> isdir0:	
  2275 00004428 6658                <1> 	pop	ax
  2276                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2277 0000442A E8AD0D0000          <1> 	call	iget
  2278                              <1> 		; jsr r0,iget / get it back in
  2279                              <1> isdir1: ; 1:
  2280 0000442F C3                  <1> 	retn
  2281                              <1> 		; rts r0
  2282                              <1> 
  2283                              <1> sysunlink:
  2284                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2285                              <1> 	; 04/12/2015 (14 byte file names)
  2286                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2287                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2288                              <1> 	;
  2289                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2290                              <1> 	; name from its directory. If this entry was the last link
  2291                              <1> 	; to the file, the contents of the file are freed and the
  2292                              <1> 	; file is destroyed. If, however, the file was open in any
  2293                              <1> 	; process, the actual destruction is delayed until it is 
  2294                              <1> 	; closed, even though the directory entry has disappeared.
  2295                              <1> 	; 
  2296                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2297                              <1> 	; does not exist or that its directory can not be written.
  2298                              <1> 	; Write permission is not required on the file itself.
  2299                              <1> 	; It is also illegal to unlink a directory (except for
  2300                              <1> 	; the superuser).
  2301                              <1> 	;
  2302                              <1> 	; Calling sequence:
  2303                              <1> 	;	sysunlink; name
  2304                              <1> 	; Arguments:
  2305                              <1> 	;	name - name of directory entry to be removed 
  2306                              <1> 	; Inputs: -
  2307                              <1> 	; Outputs: -
  2308                              <1> 	; ...............................................................
  2309                              <1> 	;				
  2310                              <1> 	; Retro UNIX 8086 v1 modification:
  2311                              <1> 	;	 The user/application program puts address of the name
  2312                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2313                              <1> 
  2314                              <1> 	; / name - remove link name
  2315 00004430 891D[64700000]      <1> 	mov	[u.namep], ebx
  2316                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2317 00004436 E891050000          <1> 	call	namei
  2318                              <1> 		; jsr r0,namei / find the i-number associated 
  2319                              <1> 			     ; / with the path name
  2320                              <1> 	;jc	error
  2321                              <1> 		; br error9 / not found
  2322 0000443B 730F                <1> 	jnc	short sysunlink1
  2323                              <1> 	; 'file not found !' error
  2324 0000443D C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2324 00004445 0000                <1>
  2325 00004447 E973F6FFFF          <1> 	jmp	error
  2326                              <1> sysunlink1:
  2327 0000444C 50                  <1> 	push	eax ; 24/12/2021
  2328                              <1> 	;push	ax
  2329                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2330 0000444D E8A9FFFFFF          <1> 	call	isdir
  2331                              <1> 		; jsr r0,isdir / is it a directory
  2332                              <1> 	;xor 	ax, ax
  2333                              <1> 	; 24/12/2021
  2334 00004452 31C0                <1> 	xor	eax, eax
  2335 00004454 66A3[7E700000]      <1> 	mov	[u.dirbuf], ax ; 0
  2336                              <1> 		; clr u.dirbuf / no, clear the location that will
  2337                              <1> 			   ; / get written into the i-number portion
  2338                              <1> 			 ; / of the entry
  2339 0000445A 832D[68700000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2340                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2341 00004461 E868000000          <1> 	call	wdir
  2342                              <1> 		; jsr r0,wdir / free the directory entry
  2343 00004466 58                  <1> 	pop	eax ; 24/12/2021
  2344                              <1> 	;pop	ax
  2345                              <1> 		; mov (sp)+,r1 / get i-number back
  2346 00004467 E8700D0000          <1> 	call	iget
  2347                              <1> 		; jsr r0,iget / get i-node
  2348 0000446C E8750E0000          <1> 	call	setimod
  2349                              <1> 		; jsr r0,setimod / set modified flag
  2350 00004471 FE0D[4A6D0000]      <1> 	dec	byte [i.nlks]
  2351                              <1> 		; decb i.nlks / decrement the number of links
  2352                              <1> 	; 24/12/2021
  2353 00004477 7505                <1> 	jnz	short sysunlink_2
  2354                              <1> 	;jnz	sysret
  2355                              <1> 		; bgt sysret9 / if this was not the last link
  2356                              <1> 			    ; / to file return
  2357                              <1> 	; AX = r1 = i-number
  2358 00004479 E8B3090000          <1> 	call	anyi
  2359                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2360                              <1> 			 ; / Then free contents of file and destroy it.
  2361                              <1> sysunlink_2:
  2362 0000447E E95CF6FFFF          <1> 	jmp	sysret
  2363                              <1> 		; br sysret9
  2364                              <1> 
  2365                              <1> mkdir:
  2366                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2367                              <1> 	; 04/12/2015 (14 byte directory names)
  2368                              <1> 	; 12/10/2015
  2369                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2370                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2371                              <1> 	;
  2372                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2373                              <1> 	; by u.namep into the current directory.
  2374                              <1> 	;
  2375                              <1> 	; INPUTS ->
  2376                              <1> 	;    u.namep - points to a file name 
  2377                              <1> 	;	           that is about to be a directory entry.
  2378                              <1> 	;    ii - current directory's i-number.	
  2379                              <1> 	; OUTPUTS ->
  2380                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2381                              <1> 	;    u.off - points to entry to be filled 
  2382                              <1> 	;	     in the current directory		
  2383                              <1> 	;    u.base - points to start of u.dirbuf.
  2384                              <1> 	;    r1 - contains i-number of current directory 
  2385                              <1> 	;	
  2386                              <1> 	; ((AX = R1)) output
  2387                              <1> 	;
  2388                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2389                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2390                              <1> 	;
  2391                              <1> 
  2392                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2393 00004483 31C0                <1> 	xor 	eax, eax
  2394 00004485 BF[80700000]        <1> 	mov     edi, u.dirbuf+2
  2395 0000448A 89FE                <1> 	mov	esi, edi
  2396 0000448C AB                  <1> 	stosd
  2397 0000448D AB                  <1> 	stosd
  2398                              <1> 	; 04/12/2015 (14 byte directory names)
  2399 0000448E AB                  <1> 	stosd
  2400 0000448F 66AB                <1> 	stosw
  2401                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2402 00004491 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2403                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2404                              <1> 	;mov 	ebp, [u.namep]
  2405 00004493 E8B3060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2406                              <1> 		; esi = physical address (page start + offset)
  2407                              <1> 		; ecx = byte count in the page (1 - 4096)
  2408                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2409                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2410                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2411                              <1> mkdir_1: ; 1: 
  2412 00004498 45                  <1> 	inc	ebp ; 12/10/2015
  2413                              <1> 	;
  2414                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2415                              <1> 	 ; 01/08/2013
  2416 00004499 AC                  <1> 	lodsb
  2417                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2418 0000449A 20C0                <1> 	and 	al, al
  2419 0000449C 7426                <1> 	jz 	short mkdir_3 	  
  2420                              <1> 		; beq 1f / if null, done
  2421 0000449E 3C2F                <1> 	cmp	al, '/'
  2422                              <1> 		; cmp r1,$'/ / is it a "/"?
  2423 000044A0 7413                <1> 	je	short mkdir_err
  2424                              <1> 	;je	error
  2425                              <1> 		; beq error9 / yes, error
  2426                              <1> 	; 12/10/2015
  2427                              <1> 	;dec	cx
  2428 000044A2 49                  <1> 	dec	ecx ; 24/12/2021
  2429 000044A3 7505                <1> 	jnz	short mkdir_2
  2430                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2431 000044A5 E8A7060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2432                              <1> 		; esi = physical address (page start + offset)
  2433                              <1> 		; ecx = byte count in the page
  2434                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2435                              <1> mkdir_2:
  2436 000044AA 81FF[8E700000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2437                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2438                              <1> 				     ; / a char?
  2439 000044B0 74E6                <1> 	je	short mkdir_1
  2440                              <1> 		; beq 1b / yes, go back
  2441 000044B2 AA                  <1> 	stosb
  2442                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2443 000044B3 EBE3                <1> 	jmp 	short mkdir_1
  2444                              <1> 		; br 1b / get next char
  2445                              <1> mkdir_err:
  2446                              <1> 	; 17/06/2015
  2447 000044B5 C705[A1700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2447 000044BD 0000                <1>
  2448 000044BF E9FBF5FFFF          <1> 	jmp	error
  2449                              <1> 
  2450                              <1> mkdir_3: ; 1:
  2451 000044C4 A1[60700000]        <1> 	mov	eax, [u.dirp]
  2452 000044C9 A3[68700000]        <1> 	mov	[u.off], eax
  2453                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2454                              <1> 				 ; / slot to u.off
  2455                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2456                              <1> 	; 29/04/2013
  2457 000044CE C705[6C700000]-     <1>         mov     dword [u.base], u.dirbuf
  2457 000044D4 [7E700000]          <1>
  2458                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2459 000044D8 C705[70700000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2459 000044E0 0000                <1>
  2460                              <1> 		; mov $10.,u.count / u.count = 10
  2461 000044E2 66A1[2C700000]      <1> 	mov	ax, [ii] 
  2462                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2463 000044E8 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2464 000044EA E8C10D0000          <1> 	call 	access
  2465                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2466                              <1> 				 ; / for writing
  2467                              <1> 	; AX = i-number of current directory
  2468                              <1> 	; 01/08/2013
  2469 000044EF FE05[B3700000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2470                              <1> 	;call	writei
  2471                              <1> 	;	; jsr r0,writei / write into directory
  2472                              <1> 	;retn	
  2473                              <1> 	;	; rts r0
  2474                              <1> 	; 24/12/2021
  2475 000044F5 E9A4100000          <1> 	jmp	writei
  2476                              <1> 
  2477                              <1> sysexec:
  2478                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2479                              <1> 	; 03/02/2022
  2480                              <1> 	; 12/01/2022
  2481                              <1> 	; 08/01/2022
  2482                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2483                              <1> 	; 23/10/2015
  2484                              <1> 	; 19/10/2015
  2485                              <1> 	; 10/10/2015, 18/10/2015
  2486                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2487                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2488                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2489                              <1> 	; 24/06/2015, 25/06/2015
  2490                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2491                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2492                              <1> 	;
  2493                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2494                              <1> 	; pointed to by 'name' in the sysexec call. 
  2495                              <1> 	; 'sysexec' performs the following operations:
  2496                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2497                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2498                              <1> 	;    3. sets trap vectors to system routines.
  2499                              <1> 	;    4. loads arguments to be passed to executing file into
  2500                              <1> 	;	highest locations of user's core
  2501                              <1> 	;    5. puts pointers to arguments in locations immediately
  2502                              <1> 	;	following arguments.
  2503                              <1> 	;    6.	saves number of arguments in next location.
  2504                              <1> 	;    7. initializes user's stack area so that all registers
  2505                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2506                              <1> 	;	to core when 'sysret' restores registers 
  2507                              <1> 	;	and does an rti.
  2508                              <1> 	;    8. inializes u.r0 and u.sp
  2509                              <1> 	;    9. zeros user's core down to u.r0
  2510                              <1> 	;   10.	reads executable file from storage device into core
  2511                              <1> 	;	starting at location 'core'.
  2512                              <1> 	;   11.	sets u.break to point to end of user's code with
  2513                              <1> 	;	data area appended.
  2514                              <1> 	;   12.	calls 'sysret' which returns control at location
  2515                              <1> 	;	'core' via 'rti' instruction. 		  		
  2516                              <1> 	;
  2517                              <1> 	; Calling sequence:
  2518                              <1> 	;	sysexec; namep; argp
  2519                              <1> 	; Arguments:
  2520                              <1> 	;	namep - points to pathname of file to be executed
  2521                              <1> 	;	argp  - address of table of argument pointers
  2522                              <1> 	;	argp1... argpn - table of argument pointers
  2523                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2524                              <1> 	; Inputs: (arguments)
  2525                              <1> 	; Outputs: -	
  2526                              <1> 	; ...............................................................
  2527                              <1> 	;
  2528                              <1> 	; Retro UNIX 386 v1 modification: 
  2529                              <1> 	;	User application runs in it's own virtual space 
  2530                              <1> 	;	which is izolated from kernel memory (and other
  2531                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2532                              <1> 	;	privilige mode. Virtual start address is always 0.
  2533                              <1> 	;	User's core memory starts at linear address 400000h
  2534                              <1> 	;	(the end of the 1st 4MB).
  2535                              <1> 	;
  2536                              <1> 	; Retro UNIX 8086 v1 modification: 
  2537                              <1> 	;	user/application segment and system/kernel segment
  2538                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2539                              <1> 	;	are different (user's registers are saved to 
  2540                              <1> 	;	and then restored from system's stack.)
  2541                              <1> 	;
  2542                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2543                              <1> 	;	      arguments which were in these registers;
  2544                              <1> 	;	      but, it returns by putting the 1st argument
  2545                              <1> 	;	      in 'u.namep' and the 2nd argument
  2546                              <1> 	;	      on top of stack. (1st argument is offset of the
  2547                              <1> 	;	      file/path name in the user's program segment.)		 	
  2548                              <1> 	
  2549                              <1> 	;call	arg2
  2550                              <1> 	; * name - 'u.namep' points to address of file/path name
  2551                              <1> 	;          in the user's program segment ('u.segmnt')
  2552                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2553                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2554                              <1> 	;          which is on top of stack.
  2555                              <1> 	;
  2556                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2557                              <1> 
  2558                              <1> 	; 23/06/2015 (32 bit modifications)
  2559                              <1> 
  2560 000044FA 891D[64700000]      <1> 	mov	[u.namep], ebx ; argument 1
  2561                              <1>         ; 18/10/2015
  2562 00004500 890D[CC700000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2563 00004506 E8C1040000          <1> 	call	namei
  2564                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2565                              <1> 			     ; / named in sysexec call in r1
  2566                              <1> 	;jc	error
  2567                              <1> 		; br error9
  2568 0000450B 731E                <1> 	jnc	short sysexec_0
  2569                              <1> 	;
  2570                              <1> 	; 'file not found !' error
  2571 0000450D C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2571 00004515 0000                <1>
  2572 00004517 E9A3F5FFFF          <1> 	jmp	error 
  2573                              <1> sysexec_not_exf:
  2574                              <1> 	; 'not executable file !' error
  2575 0000451C C705[A1700000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2575 00004524 0000                <1>
  2576 00004526 E994F5FFFF          <1> 	jmp	error 
  2577                              <1> sysexec_0:
  2578 0000452B E8AC0C0000          <1> 	call	iget
  2579                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2580                              <1> 	; 24/12/2021
  2581 00004530 F605[486D0000]10    <1> 	test	byte [i.flgs], 10h
  2582                              <1> 	;test	word [i.flgs], 10h
  2583                              <1> 	;	; bit $20,i.flgs / is file executable
  2584 00004537 74E3                <1> 	jz	short sysexec_not_exf
  2585                              <1> 	;jz	error
  2586                              <1> 		; beq error9
  2587                              <1> 	;;
  2588 00004539 E8F8140000          <1> 	call	iopen
  2589                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2590                              <1> 			     ; / given in r1 (opens file)
  2591                              <1> 	; AX = i-number of the file
  2592                              <1> 	; 24/12/2021
  2593 0000453E F605[486D0000]20    <1> 	test	byte [i.flgs], 20h
  2594                              <1> 	;test	word [i.flgs], 20h
  2595                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2596 00004545 7415                <1> 	jz	short sysexec_1
  2597                              <1> 		; beq 1f
  2598 00004547 803D[98700000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2599                              <1> 		; tstb u.uid / test user id
  2600 0000454E 760C                <1> 	jna	short sysexec_1
  2601                              <1> 		; beq 1f / super user
  2602 00004550 8A0D[4B6D0000]      <1> 	mov	cl, [i.uid]
  2603 00004556 880D[98700000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2604                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2605                              <1> 				 ; / as process user id
  2606                              <1> sysexec_1:
  2607                              <1> 	; 03/02/2022
  2608                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2609                              <1> 	; 18/10/2215
  2610                              <1> 	; 10/10/2015
  2611                              <1> 	; 21/07/2015, 24/07/2015
  2612                              <1> 	; 24/06/2015, 25/06/2015
  2613                              <1>         ; Moving arguments to the end of [u.upage]
  2614                              <1> 	; (by regarding page borders in user's memory space)
  2615                              <1> 	;
  2616                              <1> 	; 10/10/2015
  2617                              <1> 	; 21/07/2015
  2618 0000455C 89E5                <1> 	mov	ebp, esp ; (**)
  2619                              <1> 	; 18/10/2015
  2620 0000455E 89EF                <1> 	mov 	edi, ebp
  2621 00004560 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2622                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2623 00004565 29CF                <1> 	sub	edi, ecx
  2624 00004567 89FC                <1> 	mov	esp, edi
  2625 00004569 31C0                <1> 	xor	eax, eax
  2626 0000456B A3[74700000]        <1> 	mov 	[u.nread], eax ; 0
  2627                              <1> 	; 12/01/2022
  2628                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2629                              <1> 	; may leave it with any value after an error))
  2630                              <1> 	;mov	[argc], ax
  2631 00004570 A2[CA700000]        <1> 	mov	[argc], al ; 0
  2632                              <1> 	;
  2633 00004575 49                  <1> 	dec	ecx ; 256 - 1
  2634 00004576 890D[70700000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2635                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2636                              <1> sysexec_2:
  2637 0000457C 8B35[CC700000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2638 00004582 E863020000          <1> 	call	get_argp
  2639                              <1> 	;mov	ecx, 4 
  2640                              <1> 	; 03/02/2022
  2641 00004587 31C9                <1> 	xor	ecx, ecx
  2642 00004589 B104                <1> 	mov	cl, 4
  2643                              <1> sysexec_3:
  2644 0000458B 21C0                <1> 	and	eax, eax
  2645 0000458D 7455                <1> 	jz	short sysexec_6
  2646                              <1> 	; 18/10/2015
  2647 0000458F 010D[CC700000]      <1> 	add	[argv], ecx ; 4
  2648                              <1> 	;inc	word [argc]
  2649                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2650 00004595 FE05[CA700000]      <1> 	inc	byte [argc]
  2651                              <1> 	;
  2652 0000459B A3[6C700000]        <1> 	mov	[u.base], eax
  2653                              <1>  	; 23/10/2015
  2654 000045A0 66C705[B1700000]00- <1> 	mov	word [u.pcount], 0
  2654 000045A8 00                  <1>
  2655                              <1> sysexec_4:
  2656 000045A9 E81A120000          <1> 	call	cpass ; get a character from user's core memory
  2657 000045AE 750B                <1>         jnz	short sysexec_5
  2658                              <1> 		; (max. 255 chars + null)
  2659                              <1> 	; 18/10/2015
  2660 000045B0 28C0                <1> 	sub 	al, al
  2661 000045B2 AA                  <1> 	stosb
  2662 000045B3 FF05[74700000]      <1> 	inc	dword [u.nread]
  2663 000045B9 EB29                <1> 	jmp	short sysexec_6
  2664                              <1> sysexec_5:
  2665 000045BB AA                  <1> 	stosb
  2666 000045BC 20C0                <1> 	and 	al, al
  2667 000045BE 75E9                <1> 	jnz	short sysexec_4
  2668                              <1> 	;mov	ecx, 4
  2669                              <1> 	; 24/12/2021
  2670 000045C0 29C9                <1> 	sub	ecx, ecx
  2671 000045C2 B104                <1> 	mov	cl, 4
  2672                              <1> 	;cmp	[ncount], ecx ; 4
  2673                              <1> 	; 24/12/2021
  2674 000045C4 66390D[C8700000]    <1> 	cmp	[ncount], cx ; 4
  2675 000045CB 72AF                <1> 	jb	short sysexec_2
  2676 000045CD 8B35[C4700000]      <1> 	mov	esi, [nbase]
  2677 000045D3 010D[C4700000]      <1> 	add	[nbase], ecx ; 4	
  2678 000045D9 66290D[C8700000]    <1> 	sub	[ncount], cx 
  2679 000045E0 8B06                <1> 	mov	eax, [esi]
  2680 000045E2 EBA7                <1> 	jmp	short sysexec_3
  2681                              <1> sysexec_6:
  2682                              <1> 	; 18/10/2015
  2683                              <1> 	; argument list transfer from user's core memory to
  2684                              <1> 	; kernel stack frame is OK here.
  2685                              <1> 	; [u.nread] = ; argument list length
  2686                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2687                              <1> 	;
  2688                              <1> 	; 18/10/2015
  2689                              <1> 	; 24/07/2015
  2690                              <1>         ; 21/07/2015
  2691                              <1> 	; 02/07/2015
  2692                              <1> 	; 25/06/2015
  2693                              <1> 	; 24/06/2015
  2694                              <1> 	; 23/06/2015
  2695                              <1> 	;
  2696 000045E4 8B1D[A9700000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2697 000045EA 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2698 000045EC 740A                <1> 	jz	short sysexec_7
  2699 000045EE A1[A5700000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2700 000045F3 E8E6E8FFFF          <1> 	call	deallocate_page_dir
  2701                              <1> sysexec_7:
  2702 000045F8 E816E8FFFF          <1> 	call	make_page_dir
  2703                              <1> 	;jc	short sysexec_14
  2704                              <1> 	;jc	panic  ; allocation error 
  2705                              <1> 		       ; after a deallocation would be nonsence !?
  2706                              <1> 	; 08/01/2022
  2707 000045FD 7243                <1> 	jc	short sysexec_panic
  2708                              <1> 
  2709                              <1> 	; 24/07/2015
  2710                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2711                              <1> 	;     of the user's page directory
  2712                              <1> 	;     (It is needed for interrupts!)
  2713                              <1> 	; 18/10/2015
  2714 000045FF 8B15[886C0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2715 00004605 8B02                <1> 	mov	eax, [edx] ; physical address of
  2716                              <1> 			   ; kernel's first page table (1st 4 MB)
  2717                              <1> 			   ; (PDE 0 of kernel's page directory)
  2718 00004607 8B15[A5700000]      <1> 	mov 	edx, [u.pgdir]
  2719 0000460D 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2720                              <1> 	;
  2721                              <1> 	; 20/07/2015
  2722 0000460F BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2723                              <1> 	; 18/10/2015
  2724 00004614 BE[BC700000]        <1> 	mov	esi, pcore ; physical start address
  2725                              <1> sysexec_8:	
  2726 00004619 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2727 0000461E E80EE8FFFF          <1> 	call	make_page_table
  2728                              <1> 	;jc	panic
  2729                              <1> 	; 24/12/2021
  2730 00004623 721D                <1> 	jc	short sysexec_panic
  2731                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2732 00004625 E815E8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2733                              <1> 	;jc	panic
  2734                              <1> 	; 24/12/2021
  2735 0000462A 7216                <1> 	jc	short sysexec_panic
  2736                              <1> 	;
  2737 0000462C 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2738                              <1> 	; ebx = virtual address (24/07/2015)
  2739                              <1> 	; 24/12/2021
  2740                              <1> 	;call 	add_to_swap_queue
  2741                              <1> 	; 18/10/2015
  2742 0000462E 81FE[C0700000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2743 00004634 7411                <1> 	je	short sysexec_9 ; yes
  2744 00004636 BE[C0700000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2745                              <1> 	; 20/07/2015
  2746 0000463B BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2747                              <1> 	; ebx = virtual end address + segment base address - 4K
  2748 00004640 EBD7                <1>         jmp     short sysexec_8
  2749                              <1> 
  2750                              <1> sysexec_panic:
  2751                              <1> 	; 26/03/2021
  2752 00004642 E937EDFFFF          <1> 	jmp	panic
  2753                              <1> 
  2754                              <1> sysexec_9:
  2755                              <1> 	; 18/10/2015
  2756                              <1> 	; 26/08/2015
  2757                              <1> 	; 25/06/2015
  2758                              <1> 	; move arguments from kernel stack to [ecore]
  2759                              <1> 	; (argument list/line will be copied from kernel stack
  2760                              <1> 	; frame to the last (stack) page of user's core memory)
  2761                              <1> 	; 18/10/2015
  2762 00004647 8B3D[C0700000]      <1> 	mov	edi, [ecore]
  2763 0000464D 81C700100000        <1> 	add	edi, PAGE_SIZE
  2764                              <1> 	;movzx	eax, word [argc]
  2765                              <1> 	; 12/01/2022
  2766 00004653 31C0                <1> 	xor	eax, eax
  2767 00004655 A0[CA700000]        <1> 	mov	al, [argc]
  2768 0000465A 08C0                <1> 	or	al, al
  2769                              <1> 	;or	eax, eax
  2770 0000465C 7509                <1> 	jnz	short sysexec_10
  2771 0000465E 89FB                <1> 	mov 	ebx, edi
  2772 00004660 83EB04              <1> 	sub	ebx, 4 
  2773 00004663 8903                <1> 	mov	[ebx], eax ; 0
  2774 00004665 EB43                <1> 	jmp 	short sysexec_13
  2775                              <1> sysexec_10:
  2776 00004667 8B0D[74700000]      <1> 	mov	ecx, [u.nread]
  2777                              <1> 	;mov 	esi, [argv]
  2778 0000466D 89E6                <1> 	mov	esi, esp ; start address of argument list
  2779 0000466F 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2780                              <1> 
  2781                              <1> 	;;;;
  2782                              <1> 	; 09/05/2022
  2783                              <1> 	; (move edi -backward- to dword boundary)
  2784                              <1> 	; ((this will prevent 'general protection fault' error
  2785                              <1> 	;  as result of a lodsd or dword move instruction
  2786                              <1> 	;  at the end of argument list))
  2787 00004671 83EF03              <1> 	sub	edi, 3
  2788 00004674 83E7FC              <1> 	and	edi, ~3 ; (*)
  2789                              <1> 	;;;
  2790                              <1> 
  2791 00004677 89C2                <1> 	mov	edx, eax
  2792                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2793 00004679 FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2794 0000467B C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2795                              <1> 	; edx <= 128
  2796 0000467E 89FB                <1> 	mov	ebx, edi
  2797                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2798                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2799 00004680 29D3                <1> 	sub 	ebx, edx
  2800 00004682 89FA                <1> 	mov	edx, edi
  2801 00004684 F3A4                <1> 	rep	movsb
  2802 00004686 89D6                <1> 	mov 	esi, edx
  2803 00004688 89DF                <1> 	mov 	edi, ebx
  2804 0000468A BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2805 0000468F 2B15[C0700000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2806 00004695 AB                  <1> 	stosd	; eax = argument count	
  2807                              <1> sysexec_11:
  2808 00004696 89F0                <1> 	mov	eax, esi
  2809 00004698 01D0                <1> 	add	eax, edx
  2810 0000469A AB                  <1> 	stosd  ; eax = virtual address
  2811 0000469B FE0D[CA700000]      <1> 	dec	byte [argc]
  2812 000046A1 7407                <1> 	jz	short sysexec_13
  2813                              <1> sysexec_12:
  2814 000046A3 AC                  <1> 	lodsb
  2815 000046A4 20C0                <1> 	and	al, al
  2816 000046A6 75FB                <1> 	jnz	short sysexec_12
  2817 000046A8 EBEC                <1> 	jmp	short sysexec_11
  2818                              <1> 	;
  2819                              <1> 	; 1:
  2820                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2821                              <1> 			     ; / pointers to arguments to be passed
  2822                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2823                              <1> 			      ; / u.quit = 1 take quit
  2824                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2825                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2826                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2827                              <1> 			       ; / system routine
  2828                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2829                              <1> 			       ; / set to take system routine
  2830                              <1> 		; mov $sstack,sp / stack space used during swapping
  2831                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2832                              <1> 		; mov $ecore,r5 / r5 has end of core
  2833                              <1> 		; mov $core,r4 / r4 has start of users core
  2834                              <1> 		; mov r4,u.base / u.base has start of users core
  2835                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2836                              <1> 	; 1:
  2837                              <1> 		; tst (r2)+ / argument char = "nul"
  2838                              <1> 		; bne 1b
  2839                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2840                              <1> 			  ; / end of argument pointer list
  2841                              <1> 	; 1:
  2842                              <1> 	     ; / move arguments to bottom of users core
  2843                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2844                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2845                              <1> 			    ; / ptr list
  2846                              <1> 		; blo 1f / branch to 1f when all arguments
  2847                              <1> 		       ; / are moved
  2848                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2849                              <1> 	; 2:
  2850                              <1> 		; tstb (r3)+
  2851                              <1> 		; bne 2b / scan argument for \0 (nul)
  2852                              <1> 
  2853                              <1> 	; 2:
  2854                              <1> 		; movb -(r3),-(r5) / move argument char 
  2855                              <1> 				 ; / by char starting at "ecore"
  2856                              <1> 		; cmp r3,(r2) / moved all characters in 
  2857                              <1> 			    ; / this argument
  2858                              <1> 		; bhi 2b / branch 2b if not
  2859                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2860                              <1> 			     ; / r5 has pointer to nth arg
  2861                              <1> 		; br 1b / string
  2862                              <1> 	; 1:
  2863                              <1> 		; clrb -(r5)
  2864                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2865                              <1> 			; / last word of argument strings
  2866                              <1> 		; mov $core,r2
  2867                              <1> 	
  2868                              <1> 	; 1: / move argument pointers into core following 
  2869                              <1> 	      ; / argument strings
  2870                              <1> 		; cmp r2,r4
  2871                              <1> 		; bhis 1f / branch to 1f when all pointers
  2872                              <1> 			; / are moved
  2873                              <1> 		; mov (r2)+,-(r5)
  2874                              <1> 		; br 1b
  2875                              <1> 	; 1:
  2876                              <1> 		; sub $core,r4 / gives number of arguments *2
  2877                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2878                              <1> 		       ; / the number of args stored
  2879                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2880                              <1> 			     ; / of the argument pointers
  2881                              <1> sysexec_13:
  2882                              <1> 	; 19/10/2015
  2883                              <1> 	; 18/10/2015
  2884                              <1> 	; 29/07/2015
  2885                              <1> 	; 25/07/2015
  2886                              <1> 	; 24/07/2015
  2887                              <1> 	; 20/07/2015
  2888                              <1> 	; 25/06/2015
  2889                              <1> 	; 24/06/2015
  2890                              <1> 	; 23/06/2015
  2891                              <1> 	;
  2892                              <1> 	; moving arguments to [ecore] is OK here..
  2893                              <1> 	; 18/10/2015
  2894 000046AA 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2895                              <1> 	; ebx = beginning addres of argument list pointers
  2896                              <1> 	;	in user's stack
  2897                              <1> 	; 19/10/2015
  2898 000046AC 2B1D[C0700000]      <1> 	sub 	ebx, [ecore]
  2899 000046B2 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2900                              <1> 			; end of core - 4096 (last page)
  2901                              <1> 			; (virtual address)
  2902 000046B8 891D[CC700000]      <1> 	mov	[argv], ebx
  2903 000046BE 891D[78700000]      <1> 	mov	[u.break], ebx ; available user memory
  2904                              <1> 	;
  2905 000046C4 29C0                <1> 	sub	eax, eax
  2906 000046C6 C705[70700000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2906 000046CE 0000                <1>
  2907                              <1> 		; mov $14,u.count
  2908 000046D0 C705[5C700000]-     <1> 	mov	dword [u.fofp], u.off
  2908 000046D6 [68700000]          <1>
  2909                              <1> 		; mov $u.off,u.fofp
  2910 000046DA A3[68700000]        <1> 	mov	[u.off], eax ; 0
  2911                              <1> 		; clr u.off / set offset in file to be read to zero
  2912                              <1> 	; 25/07/2015
  2913 000046DF A3[6C700000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2914                              <1> 	; 25/06/2015 
  2915 000046E4 66A1[2C700000]      <1> 	mov	ax, [ii]
  2916                              <1> 	; AX = i-number of the executable file
  2917 000046EA E8C10C0000          <1> 	call	readi
  2918                              <1> 		; jsr r0,readi / read in first six words of 
  2919                              <1> 			; / user's file, starting at $core
  2920                              <1> 		; mov sp,r5 / put users stack address in r5
  2921                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2922                              <1> 				; / from r5 (leaves number of words
  2923                              <1> 				; / less 26 available for
  2924                              <1> 			     	; / program in user core
  2925                              <1> 		; mov r5,u.count /
  2926                              <1> 	; 25/06/2015
  2927 000046EF 8B0D[78700000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2928 000046F5 890D[70700000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2929                              <1> 	;
  2930 000046FB 8B0D[74700000]      <1> 	mov	ecx, [u.nread]
  2931 00004701 890D[78700000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2932 00004707 80F920              <1> 	cmp	cl, 32
  2933 0000470A 7540                <1>         jne     short sysexec_15
  2934                              <1> 	;:
  2935                              <1> 	; 25/06/2015
  2936                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2937                              <1> 	; 18/10/2015
  2938 0000470C 8B35[BC700000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2939                              <1> 		             ; (phys. start addr. of the exec. file)
  2940 00004712 AD                  <1> 	lodsd
  2941 00004713 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2942 00004717 7533                <1> 	jne	short sysexec_15
  2943                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2944                              <1> 			      ; / if file is standard a.out format
  2945                              <1> 		; bne 1f / branch, if not standard format
  2946 00004719 AD                  <1> 	lodsd
  2947 0000471A 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2948 0000471C AD                  <1> 	lodsd
  2949 0000471D 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2950                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2951                              <1> 		              ; / number of bytes in program text	
  2952                              <1> 		; sub $14,r5 / subtract 12
  2953 0000471F 89CB                <1> 	mov	ebx, ecx
  2954                              <1> 	;
  2955                              <1> 	; 25/06/2015
  2956                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2957                              <1> 	;	and SINGLIX operating systems (as code template).
  2958                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2959                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2960                              <1> 	;	Overrun is not possible for current version. 	
  2961                              <1> 	;
  2962 00004721 AD                  <1> 	lodsd	
  2963 00004722 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2964 00004724 3B1D[70700000]      <1> 	cmp	ebx, [u.count]
  2965 0000472A 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2966                              <1> 	;
  2967                              <1> 	; 24/07/2015
  2968                              <1> 	; add bss section size to [u.break]
  2969 0000472C 0105[78700000]      <1> 	add 	[u.break], eax
  2970                              <1> 	;
  2971 00004732 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2972                              <1> 	;cmp	ecx, [u.count]
  2973                              <1> 	;jnb	short sysexec_16
  2974                              <1> 		; cmp r5,u.count /
  2975                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2976 00004735 890D[70700000]      <1> 	mov	[u.count], ecx ; required read count
  2977                              <1> 		; mov r5,u.count
  2978                              <1> 	;
  2979 0000473B EB2A                <1> 	jmp	short sysexec_16
  2980                              <1> 	;
  2981                              <1> sysexec_14:
  2982                              <1> 	; 23/06/2015
  2983                              <1> 	; insufficient (out of) memory
  2984 0000473D C705[A1700000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2984 00004745 0000                <1>
  2985 00004747 E973F3FFFF          <1> 	jmp	error
  2986                              <1> 	;
  2987                              <1> sysexec_15:
  2988                              <1> 	; 25/06/2015
  2989 0000474C 0FB715[4C6D0000]    <1>         movzx   edx, word [i.size] ; file size
  2990 00004753 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2991 00004755 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2992 00004757 01D1                <1> 	add	ecx, edx ; [i.size]
  2993 00004759 3B0D[70700000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2994 0000475F 77DC                <1> 	ja	short sysexec_14
  2995 00004761 8915[70700000]      <1> 	mov	[u.count], edx
  2996                              <1> sysexec_16:
  2997 00004767 66A1[2C700000]      <1> 	mov	ax, [ii] ; i-number
  2998 0000476D E83E0C0000          <1> 	call	readi
  2999                              <1> 		; add core+10,u.nread / add size of user data area 
  3000                              <1> 		                    ; / to u.nread
  3001                              <1> 		; br 2f
  3002                              <1> 	; 1:
  3003                              <1> 		; jsr r0,readi / read in rest of file
  3004                              <1> 	; 2:
  3005 00004772 8B0D[74700000]      <1> 	mov	ecx, [u.nread]
  3006 00004778 010D[78700000]      <1> 	add	[u.break], ecx
  3007                              <1> 		; mov u.nread,u.break / set users program break to end of 
  3008                              <1> 				    ; / user code
  3009                              <1> 		; add $core+14,u.break / plus data area
  3010                              <1> sysexec_17: ; 20/07/2015
  3011                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3012                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3013                              <1> 	;;mov	ax, [ii] ; i-number
  3014                              <1> 	;call	iclose
  3015                              <1> 	;	; jsr r0,iclose / does nothing
  3016 0000477E 31C0                <1>         xor     eax, eax
  3017 00004780 FEC0                <1> 	inc	al
  3018 00004782 66A3[90700000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3019 00004788 66A3[92700000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3020                              <1> 	; 02/07/2015
  3021 0000478E 833D[A9700000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  3022 00004795 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3023                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3024 00004797 8B15[886C0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3025 0000479D 8915[A9700000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  3026                              <1> sysexec_18:
  3027                              <1> 	; 18/10/2015
  3028                              <1> 	; 05/08/2015
  3029                              <1> 	; 29/07/2015
  3030 000047A3 8B2D[CC700000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3031                              <1> 			    ; list pointers (argument count)
  3032 000047A9 FA                  <1> 	cli
  3033 000047AA 8B25[246C0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3034                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3035                              <1> 			    ; for this process	 
  3036                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3037                              <1> 	;xor	eax, eax ; 0
  3038 000047B0 FEC8                <1> 	dec	al ; eax = 0
  3039 000047B2 66BA2300            <1> 	mov	dx, UDATA
  3040 000047B6 6652                <1> 	push	dx  ; user's stack segment
  3041 000047B8 55                  <1> 	push	ebp ; user's stack pointer
  3042                              <1> 		    ; (points to number of arguments)
  3043 000047B9 FB                  <1> 	sti
  3044 000047BA 9C                  <1> 	pushfd	; EFLAGS
  3045                              <1> 		; Set IF for enabling interrupts in user mode	
  3046                              <1> 	;or	dword [esp], 200h 
  3047                              <1> 	;
  3048                              <1> 	;mov	bx, UCODE
  3049                              <1> 	;push	bx ; user's code segment
  3050 000047BB 6A1B                <1> 	push	UCODE
  3051                              <1> 	;push	0
  3052 000047BD 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3053                              <1> 		; clr -(r5) / popped into ps when rti in 
  3054                              <1> 			  ; / sysrele is executed
  3055                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3056                              <1> 		                ; / in sysrele is executed
  3057                              <1> 		;mov r5,0f / load second copyz argument
  3058                              <1> 		;tst -(r5) / decrement r5
  3059 000047BE 8925[44700000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3060                              <1> 	; 05/08/2015
  3061                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3062                              <1> 	; ('push dx' would cause to general protection fault, 
  3063                              <1> 	; after 'pop ds' etc.)
  3064                              <1> 	;
  3065                              <1> 	;; push dx ; ds (UDATA)
  3066                              <1> 	;; push dx ; es (UDATA)
  3067                              <1> 	;; push dx ; fs (UDATA)
  3068                              <1> 	;; push dx ; gs (UDATA)
  3069                              <1> 	;
  3070                              <1> 	; This is a trick to prevent general protection fault
  3071                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3072 000047C4 8EC2                <1> 	mov 	es, dx ; UDATA
  3073 000047C6 06                  <1> 	push 	es ; ds (UDATA)
  3074 000047C7 06                  <1> 	push 	es ; es (UDATA)
  3075 000047C8 06                  <1> 	push 	es ; fs (UDATA)
  3076 000047C9 06                  <1> 	push	es ; gs (UDATA)
  3077 000047CA 66BA1000            <1> 	mov	dx, KDATA
  3078 000047CE 8EC2                <1> 	mov	es, dx
  3079                              <1> 	;
  3080                              <1> 	;; pushad simulation
  3081 000047D0 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3082 000047D2 50                  <1> 	push	eax ; eax (0)
  3083 000047D3 50                  <1> 	push	eax ; ecx (0)
  3084 000047D4 50                  <1> 	push	eax ; edx (0)
  3085 000047D5 50                  <1> 	push	eax ; ebx (0)
  3086 000047D6 55                  <1> 	push	ebp ; esp before pushad
  3087 000047D7 50                  <1> 	push	eax ; ebp (0)
  3088 000047D8 50                  <1> 	push	eax ; esi (0)		
  3089 000047D9 50                  <1> 	push	eax ; edi (0)	
  3090                              <1> 	;
  3091 000047DA A3[4C700000]        <1> 	mov	[u.r0], eax ; eax = 0
  3092 000047DF 8925[48700000]      <1> 	mov	[u.usp], esp
  3093                              <1> 		; mov r5,u.r0 /
  3094                              <1> 		; sub $16.,r5 / skip 8 words
  3095                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3096                              <1> 		;             / effectively zeroes all regs
  3097                              <1> 			    ; / when sysrele is executed
  3098                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3099                              <1> 		; clr u.break
  3100                              <1> 		; mov r5,sp / point sp to user's stack
  3101                              <1> 	;
  3102 000047E5 E9F7F2FFFF          <1> 	jmp	sysret0
  3103                              <1> 	;jmp	sysret
  3104                              <1> 		; br sysret3 / return to core image at $core
  3105                              <1> 
  3106                              <1> get_argp:
  3107                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3108                              <1> 	; 18/10/2015 (nbase, ncount)
  3109                              <1> 	; 21/07/2015
  3110                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3111                              <1> 	; Get (virtual) address of argument from user's core memory
  3112                              <1> 	;
  3113                              <1> 	; INPUT:
  3114                              <1> 	;	esi = virtual address of argument pointer
  3115                              <1> 	; OUTPUT:
  3116                              <1> 	;	eax = virtual address of argument
  3117                              <1> 	;
  3118                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3119                              <1> 	;
  3120 000047EA 833D[A9700000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3121                              <1> 				    ; (the caller is kernel)
  3122                              <1> 	;jna	short get_argpk 
  3123                              <1> 	; 24/12/2021
  3124 000047F1 7719                <1> 	ja	short get_argp5
  3125                              <1> get_argpk:
  3126                              <1> 	; Argument is in kernel's memory space
  3127 000047F3 66C705[C8700000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3127 000047FB 10                  <1>
  3128 000047FC 8935[C4700000]      <1> 	mov	[nbase], esi
  3129 00004802 8305[C4700000]04    <1> 	add	dword [nbase], 4
  3130 00004809 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3131 0000480B C3                  <1> 	retn
  3132                              <1> get_argp5:
  3133 0000480C 89F3                <1>      	mov	ebx, esi
  3134 0000480E E887E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3135 00004813 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3136 00004815 A3[C4700000]        <1> 	mov 	[nbase], eax ; physical address	
  3137 0000481A 66890D[C8700000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3138 00004821 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3139                              <1> 	;cmp	cx, ax ; 4
  3140 00004826 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3141 00004828 734C                <1> 	jnb	short get_argp2
  3142 0000482A 89F3                <1> 	mov	ebx, esi
  3143 0000482C 01CB                <1> 	add	ebx, ecx
  3144 0000482E E867E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3145 00004833 7237                <1> 	jc	short get_argp_err
  3146                              <1> 	;push	esi
  3147 00004835 89C6                <1> 	mov	esi, eax
  3148 00004837 66870D[C8700000]    <1> 	xchg	cx, [ncount]
  3149 0000483E 8735[C4700000]      <1> 	xchg	esi, [nbase]
  3150 00004844 B504                <1> 	mov	ch, 4
  3151 00004846 28CD                <1> 	sub	ch, cl
  3152                              <1> get_argp0:
  3153 00004848 AC                  <1> 	lodsb
  3154                              <1> 	;push	ax
  3155                              <1> 	; 24/12/2021
  3156 00004849 50                  <1> 	push	eax
  3157 0000484A FEC9                <1> 	dec	cl
  3158 0000484C 75FA                <1>         jnz     short get_argp0
  3159 0000484E 8B35[C4700000]      <1> 	mov	esi, [nbase]
  3160                              <1> 	; 21/07/2015
  3161 00004854 0FB6C5              <1> 	movzx	eax, ch
  3162 00004857 0105[C4700000]      <1> 	add	[nbase], eax
  3163 0000485D 662905[C8700000]    <1> 	sub	[ncount], ax
  3164                              <1> get_argp1:
  3165 00004864 AC                  <1> 	lodsb
  3166 00004865 FECD                <1> 	dec	ch
  3167 00004867 7423                <1>         jz      short get_argp3
  3168                              <1> 	;push	ax
  3169                              <1> 	; 24/12/2021
  3170 00004869 50                  <1> 	push	eax
  3171 0000486A EBF8                <1> 	jmp     short get_argp1
  3172                              <1> 	; 24/12/2021
  3173                              <1> get_argp_err:
  3174 0000486C A3[A1700000]        <1> 	mov	[u.error], eax
  3175 00004871 E949F2FFFF          <1> 	jmp	error
  3176                              <1> get_argp2:
  3177                              <1> 	; 21/07/2015
  3178                              <1> 	;mov	eax, 4
  3179 00004876 8B15[C4700000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3180 0000487C 0105[C4700000]      <1> 	add	[nbase], eax
  3181 00004882 662905[C8700000]    <1> 	sub	[ncount], ax
  3182                              <1> 	;
  3183 00004889 8B02                <1> 	mov	eax, [edx]
  3184 0000488B C3                  <1> 	retn
  3185                              <1> get_argp3:
  3186 0000488C B103                <1> 	mov	cl, 3
  3187                              <1> get_argp4:
  3188 0000488E C1E008              <1> 	shl	eax, 8
  3189                              <1> 	;pop	dx
  3190                              <1> 	; 24/12/2021
  3191 00004891 5A                  <1> 	pop	edx
  3192 00004892 88D0                <1> 	mov 	al, dl
  3193 00004894 E2F8                <1>         loop    get_argp4
  3194                              <1> 	;pop	esi
  3195 00004896 C3                  <1> 	retn	
  3196                              <1> 
  3197                              <1> sysfstat:
  3198                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3199                              <1> 	;	([idev] return in eax)
  3200                              <1> 	;	0 = root device
  3201                              <1> 	;	1 = mounted device (>0)
  3202                              <1> 	; 03/02/2022
  3203                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3204                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3205                              <1> 	;
  3206                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3207                              <1> 	; on open files instead of files given by name. It puts the
  3208                              <1> 	; buffer address on the stack, gets the i-number and
  3209                              <1> 	; checks to see if the file is open for reading or writing.
  3210                              <1> 	; If the file is open for writing (i-number is negative)
  3211                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3212                              <1> 	; is made.	
  3213                              <1> 	;
  3214                              <1> 	; Calling sequence:
  3215                              <1> 	;	sysfstat; buf
  3216                              <1> 	; Arguments:
  3217                              <1> 	;	buf - buffer address
  3218                              <1> 	;
  3219                              <1> 	; Inputs: *u.r0 - file descriptor
  3220                              <1> 	; Outputs: buffer is loaded with file information
  3221                              <1> 	; ...............................................................
  3222                              <1> 	;				
  3223                              <1> 	; Retro UNIX 8086 v1 modification:
  3224                              <1> 	;       'sysfstat' system call has two arguments; so,
  3225                              <1> 	;	* 1st argument, file descriptor is in BX register
  3226                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3227                              <1> 
  3228                              <1> 	; / set status of open file
  3229                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3230 00004897 51                  <1> 	push	ecx
  3231                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3232                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3233                              <1> 		; jsr r0,getf / get the files i-number
  3234                              <1> 	; BX = file descriptor (file number)
  3235 00004898 E8FE000000          <1> 	call	getf1
  3236                              <1> 	; 03/02/2022
  3237 0000489D 21C0                <1> 	and	eax, eax
  3238                              <1> 	;and	ax, ax ; i-number of the file
  3239                              <1> 		; tst	r1 / is it 0?
  3240                              <1> 	;jz	error
  3241                              <1> 		; beq error3 / yes, error
  3242 0000489F 750F                <1> 	jnz	short sysfstat1
  3243 000048A1 C705[A1700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3243 000048A9 0000                <1>
  3244 000048AB E90FF2FFFF          <1> 	jmp	error
  3245                              <1> sysfstat1:
  3246 000048B0 80FC80              <1> 	cmp	ah, 80h
  3247 000048B3 7222                <1>         jb      short sysstat1
  3248                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3249 000048B5 66F7D8              <1> 	neg	ax
  3250                              <1> 		; neg r1 / make it positive, then branch
  3251 000048B8 EB1D                <1> 	jmp	short sysstat1
  3252                              <1> 		; br 1f / to 1f
  3253                              <1> sysstat:
  3254                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3255                              <1> 	;	([idev] return in eax)
  3256                              <1> 	;	0 = root device
  3257                              <1> 	;	1 = mounted device (>0)
  3258                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3259                              <1> 	; 18/10/2015
  3260                              <1> 	; 07/10/2015
  3261                              <1> 	; 02/09/2015
  3262                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3263                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3264                              <1> 	;
  3265                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3266                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3267                              <1> 	; long and information about the file placed in it.	
  3268                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3269                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3270                              <1> 	; is then loaded and the results are given in the UNIX
  3271                              <1> 	; Programmers Manual sysstat (II).	
  3272                              <1> 	;
  3273                              <1> 	; Calling sequence:
  3274                              <1> 	;	sysstat; name; buf
  3275                              <1> 	; Arguments:
  3276                              <1> 	;	name - points to the name of the file
  3277                              <1> 	;	buf - address of a 34 bytes buffer
  3278                              <1> 	; Inputs: -
  3279                              <1> 	; Outputs: buffer is loaded with file information
  3280                              <1> 	; ...............................................................
  3281                              <1> 	;				
  3282                              <1> 	; Retro UNIX 8086 v1 modification: 
  3283                              <1> 	;       'sysstat' system call has two arguments; so,
  3284                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3285                              <1> 	;	to get sysstat system call arguments from the user;
  3286                              <1> 	;	* 1st argument, name is pointed to by BX register
  3287                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3288                              <1> 	;
  3289                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3290                              <1> 	;	      arguments which were in these registers;
  3291                              <1> 	;	      but, it returns by putting the 1st argument
  3292                              <1> 	;	      in 'u.namep' and the 2nd argument
  3293                              <1> 	;	      on top of stack. (1st argument is offset of the
  3294                              <1> 	;	      file/path name in the user's program segment.)		 	
  3295                              <1> 	
  3296                              <1> 	; / ; name of file; buffer - get files status
  3297                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3298 000048BA 891D[64700000]      <1> 	mov	[u.namep], ebx
  3299 000048C0 51                  <1> 	push	ecx
  3300 000048C1 E806010000          <1> 	call	namei
  3301                              <1> 		; jsr r0,namei / get the i-number for the file
  3302                              <1> 	;jc	error
  3303                              <1> 		; br error3 / no such file, error
  3304 000048C6 730F                <1> 	jnc	short sysstat1
  3305                              <1> 	; pop 	ecx
  3306                              <1> sysstat_err0:
  3307                              <1> 	; 'file not found !' error
  3308 000048C8 C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3308 000048D0 0000                <1>
  3309 000048D2 E9E8F1FFFF          <1> 	jmp	error
  3310                              <1> 
  3311                              <1> ;statx: db 0
  3312                              <1> 
  3313                              <1> sysstat1: ; 1:
  3314 000048D7 E800090000          <1> 	call	iget
  3315                              <1> 		; jsr r0,iget / get the i-node into core
  3316                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3317                              <1> 	; 02/09/2015
  3318 000048DC 8F05[6C700000]      <1> 	pop	dword [u.base]
  3319                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3320 000048E2 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3321 000048E7 730A                <1> 	jnc 	short sysstat2
  3322                              <1> sysstat_err1:
  3323 000048E9 A3[A1700000]        <1> 	mov	dword [u.error], eax ; error code
  3324 000048EE E9CCF1FFFF          <1> 	jmp	error
  3325                              <1> sysstat2:
  3326 000048F3 A0[2C700000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3327 000048F8 AA                  <1> 	stosb
  3328 000048F9 FF05[6C700000]      <1> 	inc 	dword [u.base]
  3329                              <1> 	;dec 	cx
  3330                              <1> 	; 24/12/2021
  3331 000048FF 49                  <1> 	dec	ecx
  3332 00004900 7505                <1> 	jnz	short sysstat3
  3333 00004902 E841000000          <1> 	call	sysstat_gpa
  3334                              <1> 	;jc	short sysstat_err1
  3335                              <1> sysstat3:
  3336 00004907 A0[2D700000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3337 0000490C AA                  <1> 	stosb
  3338                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3339 0000490D FF05[6C700000]      <1> 	inc 	dword [u.base]
  3340                              <1> 	;;dec 	word [u.pcount]
  3341                              <1> 	;dec	cx
  3342 00004913 49                  <1> 	dec	ecx ; 24/12/2021
  3343 00004914 7505                <1> 	jnz	short sysstat4
  3344 00004916 E82D000000          <1> 	call	sysstat_gpa
  3345                              <1> 	;jc	short sysstat_err1	
  3346                              <1> sysstat4:
  3347 0000491B BE[486D0000]        <1> 	mov	esi, inode
  3348                              <1> 		; mov $inode,r2 / r2 points to i-node
  3349                              <1> sysstat5: ; 1:
  3350 00004920 A4                  <1> 	movsb
  3351                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3352 00004921 FF05[6C700000]      <1> 	inc 	dword [u.base]
  3353                              <1> 	;;dec 	word [u.pcount]
  3354                              <1> 	;dec 	cx
  3355                              <1> 	; 24/12/2021
  3356 00004927 49                  <1> 	dec	ecx
  3357 00004928 7505                <1> 	jnz	short sysstat6
  3358 0000492A E819000000          <1> 	call	sysstat_gpa
  3359                              <1> 	;jc	short sysstat_err1
  3360                              <1> sysstat6:		
  3361 0000492F 81FE[686D0000]      <1> 	cmp	esi, inode + 32
  3362                              <1> 		; cmp r2,$inode+32 / done?
  3363 00004935 75E9                <1> 	jne	short sysstat5
  3364                              <1> 		; bne 1b / no, go back
  3365                              <1> 
  3366                              <1> 	;;;
  3367                              <1> 	; 09/05/2022
  3368                              <1> 	;*** additional feature *** -retro unix only- 
  3369                              <1> 	;
  3370                              <1> 	; !! return device number -of current inode- in eax !!
  3371                              <1> 	;
  3372                              <1> 	; (modification reason/purpose:
  3373                              <1> 	; to improve 'pwd' command's pathname output/result
  3374                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3375                              <1> 	; error due to same inode numbers in root file system
  3376                              <1> 	; and mounted file system.)
  3377                              <1> 	;
  3378 00004937 29C0                <1> 	sub	eax, eax
  3379 00004939 A0[2E700000]        <1> 	mov	al, [idev] ; [cdev]
  3380 0000493E A3[4C700000]        <1> 	mov	[u.r0], eax
  3381                              <1> 	;;;  
  3382                              <1> 
  3383 00004943 E997F1FFFF          <1> 	jmp	sysret
  3384                              <1> 		; br sysret3 / return through sysret
  3385                              <1> 	;
  3386                              <1> sysstat_gpa: ; get physical address of file status buffer
  3387                              <1> 	; 02/09/2015
  3388 00004948 8B1D[6C700000]      <1> 	mov 	ebx, [u.base]
  3389                              <1> 	; 07/10/2015
  3390 0000494E E847E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3391                              <1> 	;jc	short sysstat_gpa1
  3392 00004953 7294                <1> 	jc	short sysstat_err1
  3393                              <1> 	; 18/10/2015
  3394 00004955 89C7                <1> 	mov	edi, eax ; physical address
  3395                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3396                              <1> ;sysstat_gpa1:
  3397 00004957 C3                  <1> 	retn
  3398                              <1> 
  3399                              <1> fclose:
  3400                              <1> 	; 08/01/2022
  3401                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3402                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3403                              <1> 	;            (32 bit offset pointer modification)
  3404                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3405                              <1> 	;
  3406                              <1> 	; Given the file descriptor (index to the u.fp list)
  3407                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3408                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3409                              <1> 	; u.fp list is cleared. If all the processes that opened
  3410                              <1> 	; that file close it, then fsp etry is freed and the file
  3411                              <1> 	; is closed. If not a return is taken. 
  3412                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3413                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3414                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3415                              <1> 	; a check is made to see if the file is special.	
  3416                              <1> 	;
  3417                              <1> 	; INPUTS ->
  3418                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3419                              <1> 	;    u.fp - list of entries in the fsp table
  3420                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3421                              <1> 	; OUTPUTS ->
  3422                              <1> 	;    r1 - contains the same file descriptor
  3423                              <1> 	;    r2 - contains i-number
  3424                              <1> 	;
  3425                              <1> 	; ((AX = R1))
  3426                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3427                              <1> 	;
  3428                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3429                              <1> 	;              if i-number of the file is 0. (error)  	
  3430                              <1> 
  3431                              <1> 	;movzx	edx, ax ; **
  3432                              <1> 	; 24/12/2021
  3433                              <1> 	;movzx	edx, al
  3434 00004958 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3435 0000495A 50                  <1> 	push	eax ; ***
  3436                              <1> 	;push	ax ; ***
  3437                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3438                              <1> 			     ; / the index to u.fp list)
  3439 0000495B E839000000          <1> 	call	getf
  3440                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3441                              <1> 			    ; / cdev has device =, u.fofp 
  3442                              <1> 			    ; / points to 3rd word of fsp entry
  3443 00004960 6683F801            <1> 	cmp	ax, 1 ; r1
  3444                              <1> 		; tst r1 / is i-number 0?
  3445 00004964 7231                <1> 	jb	short fclose_2
  3446                              <1> 		; beq 1f / yes, i-node not active so return
  3447                              <1> 		; tst (r0)+ / no, jump over error return
  3448 00004966 89D3                <1> 	mov	ebx, edx ; **
  3449                              <1> 	; 24/12/2021
  3450 00004968 89C2                <1> 	mov	edx, eax ; *
  3451                              <1> 	;mov 	dx, ax ; *
  3452                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3453                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3454                              <1> 			    ; / which is index to u.fp ; **
  3455 0000496A C683[52700000]00    <1> 	mov	byte [ebx+u.fp], 0
  3456                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3457 00004971 8B1D[5C700000]      <1> 	mov	ebx, [u.fofp]
  3458                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3459                              <1> fclose_0:
  3460 00004977 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3461                              <1> 		; decb 2(r1) / decrement the number of processes 
  3462                              <1> 			   ; / that have opened the file
  3463 0000497A 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3464                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3465                              <1> 	;
  3466                              <1> 	; 24/12/2021
  3467 0000497C 52                  <1> 	push	edx ; *
  3468                              <1> 	;push	dx ; *
  3469                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3470                              <1> 	;xor	ax, ax ; 0
  3471                              <1> 	; 24/12/2021
  3472 0000497D 31C0                <1> 	xor	eax, eax
  3473 0000497F 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3474                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3475 00004983 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3476                              <1> 		; tstb	3(r1) / has this file been deleted
  3477 00004986 20C0                <1> 	and	al, al
  3478 00004988 7407                <1> 	jz	short fclose_1
  3479                              <1> 		; beq 2f / no, branch
  3480                              <1> 	; 08/01/2022
  3481 0000498A 89D0                <1> 	mov	eax, edx
  3482                              <1> 	;mov	ax, dx ; *
  3483                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3484                              <1> 	; AX = inode number
  3485 0000498C E8A0040000          <1> 	call	anyi
  3486                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3487                              <1> 			    ; / check if file appears in fsp again
  3488                              <1> fclose_1: ; 2:
  3489                              <1> 	; 24/12/2021
  3490 00004991 58                  <1> 	pop	eax ; * 
  3491                              <1> 	;pop	ax ; *
  3492                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3493 00004992 E8DE110000          <1> 	call	iclose ; close if it is special file 
  3494                              <1> 		; jsr r0,iclose / check to see if its a special file
  3495                              <1> fclose_2: ; 1:
  3496                              <1> 	; 24/12/2021
  3497 00004997 58                  <1> 	pop	eax ; ***
  3498                              <1> 	;pop	ax ; ***
  3499                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3500 00004998 C3                  <1> 	retn
  3501                              <1> 		; rts r0
  3502                              <1> 
  3503                              <1> 	; 09/01/2022
  3504                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3505                              <1> getf:	; / get the device number and the i-number of an open file
  3506                              <1> 	; 13/05/2015
  3507                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3508                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3509                              <1> 	;
  3510 00004999 89C3                <1> 	mov	ebx, eax
  3511                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3512                              <1> 	; 08/01/2022
  3513 0000499B 29C0                <1> 	sub	eax, eax
  3514                              <1> 	;
  3515 0000499D 83FB0A              <1> 	cmp	ebx, 10
  3516                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3517 000049A0 7329                <1>         jnb	short getf2 ; 13/05/2015
  3518                              <1> 	;jnb	error
  3519                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3520                              <1> 			    ; / index in fsp table
  3521                              <1> 	; 08/01/2022
  3522 000049A2 8A83[52700000]      <1> 	mov	al, [ebx+u.fp]
  3523                              <1> 	;mov	bl, [ebx+u.fp]
  3524                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3525                              <1> 		                  ; / in fsp table
  3526                              <1> 	; 08/01/2022
  3527 000049A8 08C0                <1> 	or	al, al
  3528 000049AA 741F                <1> 	jz	short getf2	
  3529                              <1> 	;or	bl, bl
  3530                              <1> 	;jnz	short getf3
  3531                              <1> 	;;jz	short getf4
  3532                              <1> 		; beq 1f / if its zero return
  3533                              <1> ;getf2:
  3534                              <1> ;	; 08/01/2022
  3535                              <1> ;	; 'File not open !' error (ax=0)
  3536                              <1> ;	;sub	eax, eax
  3537                              <1> ;	retn
  3538                              <1> 
  3539                              <1> getf3:	
  3540                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3541                              <1> 	;
  3542                              <1> 	; 'fsp' table (10 bytes/entry)
  3543                              <1> 	; bit 15				   bit 0
  3544                              <1> 	; ---|-------------------------------------------
  3545                              <1> 	; r/w|		i-number of open file
  3546                              <1> 	; ---|-------------------------------------------
  3547                              <1> 	;		   device number
  3548                              <1> 	; -----------------------------------------------
  3549                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3550                              <1> 	; -----------------------------------------------
  3551                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3552                              <1> 	; ----------------------|------------------------
  3553                              <1> 	;  flag that says file 	| number of processes
  3554                              <1> 	;   has been deleted	| that have file open 
  3555                              <1> 	; ----------------------|------------------------
  3556                              <1> 	;
  3557                              <1> 	;mov	eax, 10
  3558                              <1> 	; 08/01/2022
  3559 000049AC B30A                <1> 	mov	bl, 10
  3560 000049AE F6E3                <1> 	mul	bl
  3561 000049B0 BB[126E0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3562 000049B5 01C3                <1> 	add	ebx, eax
  3563                              <1> 		; asl r1
  3564                              <1> 		; asl r1 / multiply by 8 to get index into 
  3565                              <1> 		       ; / fsp table entry
  3566                              <1> 		; asl r1
  3567                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3568                              <1> 			      ; / in the fsp entry
  3569 000049B7 891D[5C700000]      <1> 	mov	[u.fofp], ebx
  3570                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3571                              <1> 			      ; / in fsp entry in u.fofp
  3572 000049BD 4B                  <1> 	dec	ebx
  3573 000049BE 4B                  <1> 	dec	ebx
  3574                              <1> 	;mov	ax, [ebx]
  3575                              <1> 	; 09/01/2022
  3576 000049BF 8A03                <1> 	mov	al, [ebx]
  3577 000049C1 A2[2F700000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3578                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3579                              <1> 			     ;;dev number is in 1 byte
  3580                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3581 000049C6 4B                  <1> 	dec	ebx
  3582 000049C7 4B                  <1> 	dec	ebx
  3583 000049C8 668B03              <1> 	mov	ax, [ebx]
  3584                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3585                              <1> getf2:	; 08/01/2022
  3586                              <1> getf4:	; 1:
  3587 000049CB C3                  <1> 	retn
  3588                              <1> 		; rts r0
  3589                              <1> 
  3590                              <1> namei:
  3591                              <1> 	; 15/05/2022 (mounted directory path, '..' method)
  3592                              <1> 	; 03/02/2022
  3593                              <1> 	; 09/01/2022
  3594                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3595                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3596                              <1> 	; 18/10/2015 (nbase, ncount)
  3597                              <1> 	; 12/10/2015
  3598                              <1> 	; 21/08/2015
  3599                              <1> 	; 18/07/2015
  3600                              <1> 	; 02/07/2015
  3601                              <1> 	; 17/06/2015
  3602                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3603                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3604                              <1> 	;
  3605                              <1> 	; 'namei' takes a file path name and returns i-number of
  3606                              <1> 	; the file in the current directory or the root directory
  3607                              <1> 	; (if the first character of the pathname is '/').	
  3608                              <1> 	;
  3609                              <1> 	; INPUTS ->
  3610                              <1> 	;    u.namep - points to a file path name
  3611                              <1> 	;    u.cdir - i-number of users directory
  3612                              <1> 	;    u.cdev - device number on which user directory resides	
  3613                              <1> 	; OUTPUTS ->
  3614                              <1> 	;    r1 - i-number of file
  3615                              <1> 	;    cdev
  3616                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3617                              <1> 	;               occurs in the search for file path name.
  3618                              <1> 	;	        If no match u.dirb points to the end of 
  3619                              <1> 	;               the directory and r1 = i-number of the current
  3620                              <1> 	;	        directory.	
  3621                              <1> 	; ((AX = R1))
  3622                              <1> 	;
  3623                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3624                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3625                              <1> 	;
  3626                              <1> 
  3627 000049CC 66A1[50700000]      <1> 	mov	ax, [u.cdir]
  3628                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3629                              <1> 			      ; / in r1
  3630                              <1> 	; 09/01/2022
  3631 000049D2 8A15[96700000]      <1> 	mov	dl, [u.cdrv]
  3632 000049D8 8815[2F700000]      <1> 	mov	[cdev], dl
  3633                              <1> 	;mov	dx, [u.cdrv]
  3634                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3635                              <1> 				    ; device/drive number is in 1 byte, 
  3636                              <1> 				    ; not in 1 word!
  3637                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3638                              <1> 				; / into cdev
  3639                              <1> 	; 12/10/2015
  3640                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3641                              <1>       	 ; convert virtual (pathname) addr to physical address
  3642 000049DE E868010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3643                              <1> 		; esi = physical address of [u.namep]
  3644                              <1> 		; ecx = byte count in the page
  3645 000049E3 803E2F              <1> 	cmp	byte [esi], '/'
  3646                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3647 000049E6 751D                <1> 	jne	short namei_1
  3648                              <1> 		; bne 1f
  3649 000049E8 FF05[64700000]      <1> 	inc	dword [u.namep]
  3650                              <1> 		; inc u.namep / go to next char
  3651                              <1> 	;dec	cx ; remain byte count in the page
  3652                              <1> 	; 24/12/2021
  3653 000049EE 49                  <1> 	dec	ecx
  3654 000049EF 7506                <1> 	jnz	short namei_0
  3655                              <1> 	; 12/10/2015
  3656 000049F1 E855010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3657                              <1> 		; esi = physical address (page start + offset)
  3658                              <1> 		; ecx = byte count in the page
  3659 000049F6 4E                  <1> 	dec	esi
  3660                              <1> namei_0:
  3661 000049F7 46                  <1> 	inc 	esi  ; go to next char
  3662 000049F8 66A1[3A700000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3663                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3664 000049FE C605[2F700000]00    <1> 	mov	byte [cdev], 0
  3665                              <1> 		; clr cdev / clear device number
  3666                              <1> namei_1: ; 1:
  3667 00004A05 F606FF              <1> 	test	byte [esi], 0FFh
  3668                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3669 00004A08 74C1                <1> 	jz	short getf4
  3670                              <1> 	;jz	nig
  3671                              <1> 		; tstb *u.namep / is the character in file name a nul
  3672                              <1> 		; beq nig / yes, end of file name reached; 
  3673                              <1> 			; / branch to "nig"
  3674                              <1> namei_2: ; 1:
  3675                              <1> 	; 18/10/2015
  3676 00004A0A 8935[C4700000]      <1> 	mov 	[nbase], esi
  3677 00004A10 66890D[C8700000]    <1> 	mov 	[ncount], cx
  3678                              <1> 	;
  3679                              <1> 	;mov	dx, 2
  3680 00004A17 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3681 00004A19 E892080000          <1> 	call	access
  3682                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3683                              <1> 	; 'access' will not return here if user has not "r" permission !
  3684                              <1> 	; 03/02/2022
  3685 00004A1E F605[496D0000]40    <1> 	test	byte [i.flgs+1], 40h
  3686                              <1> 	;test 	word [i.flgs], 4000h
  3687                              <1> 		; bit $40000,i.flgs / directory i-node?
  3688 00004A25 746A                <1>         jz      short namei_err
  3689                              <1> 		; beq error3 / no, got an error
  3690                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3691 00004A27 31C0                <1> 	xor	eax, eax
  3692 00004A29 A3[68700000]        <1> 	mov	[u.off], eax ; 0
  3693 00004A2E 66A1[4C6D0000]      <1> 	mov	ax, [i.size]
  3694 00004A34 A3[60700000]        <1> 	mov	[u.dirp], eax
  3695                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3696                              <1> 		; clr u.off / u.off is file offset used by user
  3697 00004A39 C705[5C700000]-     <1> 	mov	dword [u.fofp], u.off
  3697 00004A3F [68700000]          <1>
  3698                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3699                              <1> 				  ; / the offset portion of fsp entry
  3700                              <1> namei_3: ; 2:
  3701 00004A43 C705[6C700000]-     <1> 	mov	dword [u.base], u.dirbuf
  3701 00004A49 [7E700000]          <1>
  3702                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3703                              <1> 				    ; / copied from a directory
  3704 00004A4D C705[70700000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3704 00004A55 0000                <1>
  3705                              <1>  		; mov $10.,u.count / u.count is byte count 
  3706                              <1> 				 ; / for reads and writes
  3707 00004A57 66A1[2C700000]      <1> 	mov 	ax, [ii]
  3708                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3709 00004A5D FE05[B3700000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3710 00004A63 E848090000          <1>     	call	readi
  3711                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3712                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3713 00004A68 8B0D[74700000]      <1> 	mov 	ecx, [u.nread]
  3714 00004A6E 09C9                <1> 	or 	ecx, ecx
  3715                              <1> 		; tst u.nread
  3716 00004A70 741B                <1> 	jz	short nib
  3717                              <1> 		; ble nib / gives error return
  3718                              <1> 	;
  3719 00004A72 668B1D[7E700000]    <1> 	mov 	bx, [u.dirbuf]
  3720 00004A79 6621DB              <1> 	and 	bx, bx       
  3721                              <1> 		; tst u.dirbuf /
  3722 00004A7C 7522                <1> 	jnz	short namei_4
  3723                              <1> 		; bne 3f / branch when active directory entry 
  3724                              <1> 		       ; / (i-node word in entry non zero)
  3725 00004A7E A1[68700000]        <1> 	mov	eax, [u.off]
  3726 00004A83 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3727 00004A86 A3[60700000]        <1> 	mov	[u.dirp], eax
  3728                              <1> 		; mov u.off,u.dirp
  3729                              <1> 		; sub $10.,u.dirp
  3730 00004A8B EBB6                <1> 	jmp	short namei_3
  3731                              <1> 		; br 2b
  3732                              <1> 
  3733                              <1> 	; 18/07/2013
  3734                              <1> nib: 
  3735 00004A8D 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3736 00004A8F F9                  <1> 	stc
  3737                              <1> nig:
  3738 00004A90 C3                  <1> 	retn
  3739                              <1> 
  3740                              <1> namei_err:
  3741                              <1> 	; 16/06/2015
  3742 00004A91 C705[A1700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3742 00004A99 0000                <1>
  3743 00004A9B E91FF0FFFF          <1> 	jmp	error
  3744                              <1> 
  3745                              <1> namei_4: ; 3:
  3746                              <1> 	; 18/10/2015
  3747                              <1> 	; 12/10/2015
  3748                              <1> 	; 21/08/2015
  3749                              <1> 	; 18/07/2015
  3750 00004AA0 8B2D[64700000]      <1> 	mov	ebp, [u.namep]
  3751                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3752 00004AA6 BF[80700000]        <1> 	mov 	edi, u.dirbuf + 2
  3753                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3754                              <1> 	; 18/10/2015
  3755 00004AAB 8B35[C4700000]      <1> 	mov	esi, [nbase]	
  3756 00004AB1 668B0D[C8700000]    <1> 	mov	cx, [ncount]
  3757                              <1> 	;
  3758 00004AB8 6621C9              <1> 	and	cx, cx
  3759 00004ABB 7505                <1> 	jnz	short namei_5	
  3760                              <1> 	;
  3761 00004ABD E88F000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3762                              <1> 		; esi = physical address (page start + offset)
  3763                              <1> 		; ecx = byte count in the page
  3764                              <1> namei_5: ; 3:
  3765 00004AC2 45                  <1> 	inc	ebp ; 18/07/2015
  3766 00004AC3 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3767                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3768 00004AC4 08C0                <1> 	or 	al, al
  3769 00004AC6 741C                <1> 	jz 	short namei_7
  3770                              <1> 		; beq 3f / if char is nul, then the last char in string
  3771                              <1> 			; / has been moved
  3772 00004AC8 3C2F                <1> 	cmp	al, '/'
  3773                              <1> 		; cmp r4,$'/ / is char a </>
  3774 00004ACA 7418                <1> 	je 	short namei_7
  3775                              <1> 		; beq 3f	
  3776                              <1> 	; 24/12/2021
  3777 00004ACC 49                  <1> 	dec	ecx
  3778                              <1> 	; 12/10/2015
  3779                              <1> 	;dec	cx ; remain byte count in the page
  3780 00004ACD 7505                <1> 	jnz	short namei_6
  3781 00004ACF E87D000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3782                              <1> 		; esi = physical address (page start + offset)
  3783                              <1> 		; ecx = byte count in the page
  3784                              <1> namei_6:
  3785 00004AD4 81FF[8E700000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3786                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3787                              <1> 				     ; / all 8 bytes of file name
  3788 00004ADA 74E6                <1> 	je	short namei_5
  3789                              <1> 		; beq 3b
  3790 00004ADC AE                  <1> 	scasb	
  3791                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3792                              <1> 			      ; / char read from directory
  3793 00004ADD 74E3                <1> 	je 	short namei_5
  3794                              <1> 		; beq 3b / branch if chars match
  3795                              <1> namei_9:
  3796 00004ADF E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3797                              <1> 		; br 2b / file names do not match go to next directory entry
  3798                              <1> namei_7: ; 3:
  3799 00004AE4 81FF[8E700000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3800                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3801 00004AEA 7406                <1> 	je	short namei_8
  3802                              <1> 		; beq 3f
  3803 00004AEC 8A27                <1> 	mov 	ah, [edi]
  3804                              <1> 	;inc 	edi 
  3805 00004AEE 20E4                <1> 	and 	ah, ah
  3806                              <1> 		; tstb (r3)+ /
  3807                              <1>         ;jnz	namei_3
  3808                              <1> 		; bne 2b
  3809                              <1> 	; 24/12/2021
  3810 00004AF0 75ED                <1> 	jnz	short namei_9	
  3811                              <1> namei_8: ; 3
  3812 00004AF2 892D[64700000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3813                              <1> 		; mov r2,u.namep / u.namep points to char 
  3814                              <1> 			       ; / following a / or nul
  3815                              <1> 	;mov	bx, [u.dirbuf]
  3816                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3817                              <1> 				; / entry to r1
  3818                              <1> 	;;;;
  3819                              <1> 	; 15/05/2022 - Retro UNIX (8086/386) feature only !
  3820                              <1> 	; ! 'pwd' utility modification !
  3821                              <1> 	; ((if directory entry name is a dotdot)))
  3822                              <1> 	;; check if it is mounted device's root directory inode
  3823                              <1> 	; and if so, replace it with parent dir inode number
  3824                              <1> 	;  of mounting directory in [mntp].
  3825                              <1> 
  3826 00004AF8 668B1D[7E700000]    <1> 	mov	bx, [u.dirbuf]
  3827                              <1> 
  3828 00004AFF 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3829 00004B03 753C                <1> 	jne	short namei_11
  3830                              <1> 
  3831 00004B05 663B1D[2C700000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3832 00004B0C 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3833                              <1> 
  3834                              <1> 	;cmp	[idev], bh ; 0
  3835 00004B0E 383D[2F700000]      <1> 	cmp	[cdev], bh ; 0
  3836                              <1> 			; 0 = root fs, dev num in [rdev]
  3837                              <1> 			; 1 = mounted, dev num in [mdev]
  3838 00004B14 762B                <1> 	jna	short namei_11
  3839                              <1> 
  3840                              <1> 	; dotdot (parent directory link) check
  3841 00004B16 66813D[80700000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3841 00004B1E 2E                  <1>
  3842 00004B1F 7520                <1> 	jne	short namei_11
  3843 00004B21 803D[82700000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3844 00004B28 7517                <1> 	jne	short namei_11
  3845                              <1> 	
  3846                              <1> 	; (This may not be necessary because [idev] = 1
  3847                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3848 00004B2A 66391D[34700000]    <1> 	cmp	[mnti], bx ; 41
  3849 00004B31 760E                <1> 	jna	short namei_11
  3850                              <1> 	
  3851                              <1> 	; change inumber to parent dir inum of mount directory
  3852 00004B33 668B1D[36700000]    <1> 	mov	bx, [mntp]
  3853 00004B3A C605[2F700000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3854                              <1> namei_11:
  3855                              <1> 	;;;;
  3856                              <1> 
  3857 00004B41 20C0                <1> 	and 	al, al
  3858                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3859                              <1> 		      ;  / if r4 = </> then go to next directory
  3860                              <1> 	; 15/05/2022
  3861 00004B43 6689D8              <1> 	mov	ax, bx
  3862                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3863                              <1>   	; 24/12/2021
  3864 00004B46 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3865                              <1> 	;jnz	namei_2 
  3866                              <1> 		; bne 1b
  3867                              <1> 	; AX = i-number of the file
  3868                              <1> ;;nig:
  3869                              <1> 	;retn	; 24/12/2021
  3870                              <1> 		; tst (r0)+ / gives non-error return
  3871                              <1> ;;nib:
  3872                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3873                              <1> 		       ; ax = 0 -> file not found 
  3874                              <1> ;;	stc	; 27/05/2013
  3875                              <1> ;;	retn
  3876                              <1> 		; rts r0
  3877                              <1> 
  3878                              <1> trans_addr_nmbp:
  3879                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3880                              <1> 	; 18/10/2015
  3881                              <1> 	; 12/10/2015
  3882 00004B4B 8B2D[64700000]      <1> 	mov 	ebp, [u.namep]
  3883                              <1> trans_addr_nm:
  3884                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3885                              <1> 	; Convert virtual (pathname) address to physical address
  3886                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3887                              <1> 	; 18/10/2015
  3888                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3889                              <1> 	; 02/07/2015
  3890                              <1> 	; 17/06/2015
  3891                              <1> 	; 16/06/2015
  3892                              <1> 	;
  3893                              <1> 	; INPUTS: 
  3894                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3895                              <1> 	;	[u.pgdir] = user's page directory
  3896                              <1> 	; OUTPUT:
  3897                              <1> 	;       esi = physical address of the pathname
  3898                              <1> 	;	ecx = remain byte count in the page
  3899                              <1> 	;
  3900                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3901                              <1> 	;
  3902                              <1> 
  3903                              <1> 	; 08/01/2022
  3904 00004B51 29C9                <1> 	sub	ecx, ecx
  3905                              <1> 	;
  3906 00004B53 833D[A9700000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3907 00004B5A 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3908                              <1> 				     ; it is already physical address
  3909 00004B5C 50                  <1>    	push	eax	
  3910 00004B5D 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3911 00004B5F E836E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3912 00004B64 7204                <1> 	jc	short tr_addr_nm_err
  3913                              <1> 	; 18/10/2015
  3914                              <1> 	; eax = physical address 
  3915                              <1> 	; cx = remain byte count in page (1-4096) 
  3916                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3917 00004B66 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3918 00004B68 58                  <1> 	pop	eax 
  3919 00004B69 C3                  <1> 	retn
  3920                              <1> 
  3921                              <1> tr_addr_nm_err:
  3922 00004B6A A3[A1700000]        <1> 	mov	[u.error], eax
  3923                              <1> 	;pop 	eax
  3924 00004B6F E94BEFFFFF          <1> 	jmp	error
  3925                              <1> 
  3926                              <1> trans_addr_nmk:
  3927                              <1> 	; 12/10/2015
  3928                              <1> 	; 02/07/2015
  3929 00004B74 8B35[64700000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3930                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3931                              <1> 	; 08/01/2022
  3932 00004B7A B510                <1> 	mov	ch, PAGE_SIZE/256
  3933 00004B7C C3                  <1> 	retn
  3934                              <1> 
  3935                              <1> syschdir:
  3936                              <1> 	; / makes the directory specified in the argument
  3937                              <1> 	; / the current directory
  3938                              <1> 	;
  3939                              <1> 	; 09/01/2022
  3940                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3941                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3942                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3943                              <1> 	;
  3944                              <1> 	; 'syschdir' makes the directory specified in its argument
  3945                              <1> 	; the current working directory.
  3946                              <1> 	;
  3947                              <1> 	; Calling sequence:
  3948                              <1> 	;	syschdir; name
  3949                              <1> 	; Arguments:
  3950                              <1> 	;	name - address of the path name of a directory
  3951                              <1> 	;	       terminated by nul byte.	
  3952                              <1> 	; Inputs: -
  3953                              <1> 	; Outputs: -
  3954                              <1> 	; ...............................................................
  3955                              <1> 	;				
  3956                              <1> 	; Retro UNIX 8086 v1 modification:
  3957                              <1> 	;	 The user/application program puts address of 
  3958                              <1> 	;	 the path name in BX register as 'syschdir' 
  3959                              <1> 	; 	 system call argument.
  3960                              <1> 
  3961 00004B7D 891D[64700000]      <1> 	mov	[u.namep], ebx
  3962                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3963 00004B83 E844FEFFFF          <1> 	call	namei
  3964                              <1> 		; jsr r0,namei / find its i-number
  3965                              <1> 	;jc	error
  3966                              <1> 		; br error3
  3967 00004B88 730F                <1> 	jnc	short syschdir0
  3968                              <1> 	; 'directory not found !' error
  3969 00004B8A C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3969 00004B92 0000                <1>
  3970 00004B94 E926EFFFFF          <1> 	jmp	error
  3971                              <1> syschdir0:
  3972                              <1> 	; 08/01/2022
  3973 00004B99 B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3974 00004B9B E810070000          <1> 	call	access
  3975                              <1> 		; jsr r0,access; 2 / get i-node into core
  3976                              <1> 	; 08/01/2022
  3977 00004BA0 F605[496D0000]40    <1> 	test	byte [i.flgs+1], 40h
  3978                              <1> 	;test	word [i.flgs], 4000h
  3979                              <1> 		; bit $40000,i.flgs / is it a directory?
  3980                              <1> 	;jz	error 
  3981                              <1> 		; beq error3 / no error
  3982 00004BA7 750F                <1> 	jnz	short syschdir1
  3983 00004BA9 C705[A1700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3983 00004BB1 0000                <1>
  3984 00004BB3 E907EFFFFF          <1> 	jmp	error
  3985                              <1> syschdir1:
  3986 00004BB8 66A3[50700000]      <1> 	mov	[u.cdir], ax
  3987                              <1> 		; mov r1,u.cdir / move i-number to users 
  3988                              <1> 			      ; / current directory
  3989                              <1> 	; 09/01/2022
  3990 00004BBE A0[2F700000]        <1> 	mov	al, [cdev]
  3991 00004BC3 A2[96700000]        <1> 	mov	[u.cdrv], al
  3992                              <1> 	;mov	ax, [cdev]
  3993                              <1> 	;mov	[u.cdrv], ax
  3994                              <1> 		; mov cdev,u.cdev / move its device to users 
  3995                              <1> 			        ; / current device
  3996 00004BC8 E912EFFFFF          <1> 	jmp	sysret
  3997                              <1> 		; br sysret3
  3998                              <1> 
  3999                              <1> syschmod: ; < change mode of file >
  4000                              <1> 	; 29/04/2022 (bugfix)
  4001                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4002                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4003                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4004                              <1> 	;
  4005                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4006                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4007                              <1> 	; changed to 'mode'.
  4008                              <1> 	;
  4009                              <1> 	; Calling sequence:
  4010                              <1> 	;	syschmod; name; mode
  4011                              <1> 	; Arguments:
  4012                              <1> 	;	name - address of the file name
  4013                              <1> 	;	       terminated by null byte.
  4014                              <1> 	;	mode - (new) mode/flags < attributes >
  4015                              <1> 	;	
  4016                              <1> 	; Inputs: -
  4017                              <1> 	; Outputs: -
  4018                              <1> 	; ...............................................................
  4019                              <1> 	;				
  4020                              <1> 	; Retro UNIX 8086 v1 modification: 
  4021                              <1> 	;       'syschmod' system call has two arguments; so,
  4022                              <1> 	;	* 1st argument, name is pointed to by BX register
  4023                              <1> 	;	* 2nd argument, mode is in CX register
  4024                              <1> 	;
  4025                              <1> 	; Mode bits (Flags):
  4026                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4027                              <1> 	;	bit 14 - directory flag (4000h)
  4028                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4029                              <1> 	;	bit 12 - large file flag (1000h)
  4030                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4031                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4032                              <1> 	;	bit 4 - executable flag (10h)
  4033                              <1> 	;	bit 3 - read permission for owner (08h)
  4034                              <1> 	;	bit 2 - write permission for owner (04h)
  4035                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4036                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4037                              <1> 
  4038                              <1> 	; / name; mode
  4039 00004BCD E815000000          <1> 	call	isown
  4040                              <1> 		;jsr r0,isown / get the i-node and check user status
  4041                              <1> 	; 09/01/2022
  4042 00004BD2 F605[496D0000]40    <1> 	test	byte [i.flgs+1], 40h
  4043                              <1> 	;test	word [i.flgs], 4000h
  4044                              <1> 		; bit $40000,i.flgs / directory?
  4045 00004BD9 7402                <1> 	jz	short syschmod1
  4046                              <1> 		; beq 2f / no
  4047                              <1> 	; AL = (new) mode
  4048 00004BDB 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4049                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  4050                              <1> 			   ; / executable modes
  4051                              <1> syschmod1: ; 2:
  4052 00004BDD A2[486D0000]        <1> 	mov	[i.flgs], al	
  4053                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  4054                              <1> 	;jmp	short isown1
  4055                              <1> 	;	; br 1f ; (jmp sysret4)
  4056                              <1> 	; 29/04/2022
  4057 00004BE2 E9F8EEFFFF          <1> 	jmp	sysret
  4058                              <1> 
  4059                              <1> isown:
  4060                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4061                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4062                              <1> 	;
  4063                              <1> 	; 'isown' is given a file name (the 1st argument).
  4064                              <1> 	;  It find the i-number of that file via 'namei' 
  4065                              <1> 	;  then gets the i-node into core via 'iget'.
  4066                              <1> 	;  It then tests to see if the user is super user. 
  4067                              <1> 	;  If not, it cheks to see if the user is owner of 
  4068                              <1> 	;  the file. If he is not an error occurs.
  4069                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4070                              <1> 	;  the inode has been modified and the 2nd argument of
  4071                              <1> 	;  the call is put in r2.
  4072                              <1> 	;
  4073                              <1> 	; INPUTS ->
  4074                              <1> 	;    arguments of syschmod and syschown calls
  4075                              <1> 	; OUTPUTS ->
  4076                              <1> 	;    u.uid - id of user
  4077                              <1> 	;    imod - set to a 1
  4078                              <1> 	;    r2 - contains second argument of the system call				 	
  4079                              <1> 	;
  4080                              <1> 	;   ((AX=R2) output as 2nd argument)
  4081                              <1> 	;
  4082                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4083                              <1> 	;
  4084                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4085                              <1> 	;; ! 2nd argument on top of stack !
  4086                              <1> 	;; 22/06/2015 - 32 bit modifications
  4087                              <1> 	;; 07/07/2013
  4088 00004BE7 891D[64700000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4089 00004BED 51                  <1> 	push 	ecx ;; 2nd argument
  4090                              <1> 	;;
  4091 00004BEE E8D9FDFFFF          <1> 	call	namei
  4092                              <1> 		; jsr r0,namei / get its i-number
  4093                              <1>        ; Retro UNIX 8086 v1 modification !
  4094                              <1>        ; ax = 0 -> file not found 
  4095                              <1> 	;and	ax, ax
  4096                              <1> 	;jz	error
  4097                              <1> 	;jc	error ; 27/05/2013
  4098                              <1> 		; br error3
  4099 00004BF3 730F                <1> 	jnc	short isown0
  4100                              <1> 	; 'file not found !' error
  4101 00004BF5 C705[A1700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4101 00004BFD 0000                <1>
  4102 00004BFF E9BBEEFFFF          <1> 	jmp	error
  4103                              <1> isown0:
  4104 00004C04 E8D3050000          <1> 	call	iget
  4105                              <1> 		; jsr r0,iget / get i-node into core
  4106 00004C09 A0[98700000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4107 00004C0E 08C0                <1> 	or	al, al
  4108                              <1> 		; tstb u.uid / super user?
  4109 00004C10 7417                <1> 	jz	short isown1
  4110                              <1> 		; beq 1f / yes, branch
  4111 00004C12 3A05[4B6D0000]      <1> 	cmp	al, [i.uid]
  4112                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4113                              <1> 				 ; / the file
  4114                              <1> 	;jne	error
  4115                              <1> 		; beq 1f / yes
  4116                              <1> 		; jmp error3 / no, error
  4117 00004C18 740F                <1> 	je	short isown1
  4118                              <1> 
  4119 00004C1A C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4119 00004C22 0000                <1>
  4120                              <1> 			;  'permission denied !' error
  4121 00004C24 E996EEFFFF          <1> 	jmp	error
  4122                              <1> isown1: ; 1:
  4123 00004C29 E8B8060000          <1> 	call	setimod
  4124                              <1> 		; jsr r0,setimod / indicates 
  4125                              <1> 		;	       ; / i-node has been modified
  4126 00004C2E 58                  <1> 	pop	eax ; 2nd argument
  4127                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4128                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4129 00004C2F C3                  <1> 	retn
  4130                              <1> 		; rts r0
  4131                              <1> 
  4132                              <1> ;;arg:  ; < get system call arguments >
  4133                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4134                              <1> 	; of form:
  4135                              <1> 	;	sys 'routine' ; arg1
  4136                              <1> 	;		or
  4137                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4138                              <1> 	;		or
  4139                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4140                              <1> 	;	
  4141                              <1> 	; INPUTS ->
  4142                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4143                              <1> 	;	This pointers's value is actually the value of
  4144                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4145                              <1> 	;	made to process the sys instruction
  4146                              <1> 	;    r0 - contains the return address for the routine
  4147                              <1> 	;	that called arg. The data in the word pointer 
  4148                              <1> 	;	to by the return address is used as address
  4149                              <1> 	;	in which the extracted argument is stored   		
  4150                              <1> 	;    	
  4151                              <1> 	; OUTPUTS ->
  4152                              <1> 	;    'address' - contains the extracted argument 
  4153                              <1> 	;    u.sp+18 - is incremented by 2 
  4154                              <1> 	;    r1 - contains the extracted argument
  4155                              <1> 	;    r0 - points to the next instruction to be
  4156                              <1> 	;	 executed in the calling routine.
  4157                              <1> 	;
  4158                              <1>   
  4159                              <1> 	; mov u.sp,r1
  4160                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4161                              <1> 			; / into argument of arg2
  4162                              <1> 	; add $2,18.(r1) / point pc on stack 
  4163                              <1> 			      ; / to next system argument
  4164                              <1> 	; rts r0
  4165                              <1> 
  4166                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4167                              <1> 	; 'arg2' takes first argument in system call
  4168                              <1> 	;  (pointer to name of the file) and puts it in location
  4169                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4170                              <1> 	;  and on top of the stack
  4171                              <1> 	;	
  4172                              <1> 	; INPUTS ->
  4173                              <1> 	;    u.sp, r0
  4174                              <1> 	;    	
  4175                              <1> 	; OUTPUTS ->
  4176                              <1> 	;    u.namep
  4177                              <1> 	;    u.off 
  4178                              <1> 	;    u.off pushed on stack
  4179                              <1> 	;    r1
  4180                              <1> 	;
  4181                              <1> 
  4182                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4183                              <1> 				; / first arg in sys call
  4184                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4185                              <1> 				; / second arg in sys call
  4186                              <1> 	; mov r0,r1 / r0 points to calling routine
  4187                              <1> 	; mov (sp),r0 / put operation code back in r0
  4188                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4189                              <1> 			; / on stack
  4190                              <1> 	; jmp (r1) / return to calling routine
  4191                              <1> 
  4192                              <1> syschown: ; < change owner of file >
  4193                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4194                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4195                              <1> 	;
  4196                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4197                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4198                              <1> 	; changed to 'owner'
  4199                              <1> 	;
  4200                              <1> 	; Calling sequence:
  4201                              <1> 	;	syschown; name; owner
  4202                              <1> 	; Arguments:
  4203                              <1> 	;	name - address of the file name
  4204                              <1> 	;	       terminated by null byte.
  4205                              <1> 	;	owner - (new) owner (number/ID)
  4206                              <1> 	;	
  4207                              <1> 	; Inputs: -
  4208                              <1> 	; Outputs: -
  4209                              <1> 	; ...............................................................
  4210                              <1> 	;				
  4211                              <1> 	; Retro UNIX 8086 v1 modification: 
  4212                              <1> 	;       'syschown' system call has two arguments; so,
  4213                              <1> 	;	* 1st argument, name is pointed to by BX register
  4214                              <1> 	;	* 2nd argument, owner number is in CX register
  4215                              <1> 	;
  4216                              <1> 	; / name; owner
  4217 00004C30 E8B2FFFFFF          <1> 	call	isown
  4218                              <1> 		; jsr r0,isown / get the i-node and check user status
  4219 00004C35 803D[98700000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4220                              <1> 		; tstb u.uid / super user
  4221 00004C3C 7418                <1> 	jz	short syschown1
  4222                              <1> 		; beq 2f / yes, 2f
  4223 00004C3E F605[486D0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4224                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4225                              <1> 	;jnz	error
  4226                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4227 00004C45 740F                <1> 	jz	short syschown1
  4228                              <1> 	; 'permission denied !'
  4229 00004C47 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4229 00004C4F 0000                <1>
  4230 00004C51 E969EEFFFF          <1> 	jmp	error
  4231                              <1> syschown1: ; 2:
  4232                              <1> 	; AL = owner (number/ID)
  4233 00004C56 A2[4B6D0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4234                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4235                              <1> 			       ; / in the i-node
  4236 00004C5B E97FEEFFFF          <1> 	jmp	sysret
  4237                              <1> 	; 1: 
  4238                              <1> 		; jmp sysret4
  4239                              <1> 	; 3:
  4240                              <1> 		; jmp	error
  4241                              <1> 
  4242                              <1> systime: ; / get time of year
  4243                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4244                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4245                              <1> 	;
  4246                              <1> 	; 20/06/2013
  4247                              <1> 	; 'systime' gets the time of the year.
  4248                              <1> 	; The present time is put on the stack.
  4249                              <1> 	;
  4250                              <1> 	; Calling sequence:
  4251                              <1> 	;	systime
  4252                              <1> 	; Arguments: -
  4253                              <1> 	;	
  4254                              <1> 	; Inputs: -
  4255                              <1> 	; Outputs: sp+2, sp+4 - present time
  4256                              <1> 	; ...............................................................
  4257                              <1> 	;	
  4258                              <1> 	; Retro UNIX 8086 v1 modification: 
  4259                              <1> 	;       'systime' system call will return to the user
  4260                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4261                              <1> 	;
  4262                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4263                              <1> 	;	system call for PC compatibility !!		 	
  4264                              <1> 
  4265 00004C60 E8A8E9FFFF          <1> 	call 	epoch
  4266 00004C65 A3[4C700000]        <1> 	mov 	[u.r0], eax
  4267                              <1> 		; mov s.time,4(sp)
  4268                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4269                              <1> 				   ; / on the stack
  4270                              <1> 		; br sysret4
  4271 00004C6A E970EEFFFF          <1> 	jmp	sysret 
  4272                              <1> 
  4273                              <1> sysstime: ; / set time
  4274                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4275                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4276                              <1> 	;
  4277                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4278                              <1> 	;
  4279                              <1> 	; Calling sequence:
  4280                              <1> 	;	sysstime
  4281                              <1> 	; Arguments: -
  4282                              <1> 	;	
  4283                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4284                              <1> 	; Outputs: -
  4285                              <1> 	; ...............................................................
  4286                              <1> 	;	
  4287                              <1> 	; Retro UNIX 8086 v1 modification: 
  4288                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4289                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4290                              <1> 	; 
  4291                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4292                              <1> 	;	to get sysstime system call arguments from the user;
  4293                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4294                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4295                              <1> 	;
  4296                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4297                              <1> 	;	system call for PC compatibility !!	
  4298                              <1> 
  4299 00004C6F 803D[98700000]00    <1> 	cmp	byte [u.uid], 0
  4300                              <1> 		; tstb u.uid / is user the super user
  4301                              <1> 	;ja	error
  4302                              <1> 		; bne error4 / no, error
  4303 00004C76 760F                <1> 	jna	short systime1
  4304                              <1> 	; 'permission denied !'
  4305 00004C78 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4305 00004C80 0000                <1>
  4306 00004C82 E938EEFFFF          <1> 	jmp	error
  4307                              <1> systime1:
  4308                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4309                              <1> 	; EBX = unix (epoch) time (from user)
  4310 00004C87 89D8                <1> 	mov	eax, ebx
  4311 00004C89 E8FFEAFFFF          <1> 	call 	set_date_time
  4312                              <1> 		; mov 4(sp),s.time
  4313                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4314 00004C8E E94CEEFFFF          <1> 	jmp	sysret
  4315                              <1> 		; br sysret4
  4316                              <1> 
  4317                              <1> sysbreak:
  4318                              <1> 	; 18/10/2015
  4319                              <1> 	; 07/10/2015
  4320                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4321                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4322                              <1> 	;
  4323                              <1> 	; 'sysbreak' sets the programs break points. 
  4324                              <1> 	; It checks the current break point (u.break) to see if it is
  4325                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4326                              <1> 	; even address (if it was odd) and the area between u.break
  4327                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4328                              <1> 	; in u.break and control is passed to 'sysret'.
  4329                              <1> 	;
  4330                              <1> 	; Calling sequence:
  4331                              <1> 	;	sysbreak; addr
  4332                              <1> 	; Arguments: -
  4333                              <1> 	;	
  4334                              <1> 	; Inputs: u.break - current breakpoint
  4335                              <1> 	; Outputs: u.break - new breakpoint 
  4336                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4337                              <1> 	; ...............................................................
  4338                              <1> 	;	
  4339                              <1> 	; Retro UNIX 8086 v1 modification:
  4340                              <1> 	;	The user/application program puts breakpoint address
  4341                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4342                              <1> 	; 	(argument transfer method 1)
  4343                              <1> 	;
  4344                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4345                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4346                              <1> 	;  NOTE:
  4347                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4348                              <1> 	;	'u.break' address) of user's memory for original unix's
  4349                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4350                              <1> 
  4351                              <1> 		; mov u.break,r1 / move users break point to r1
  4352                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4353                              <1> 		; blos 1f / yes, 1f
  4354                              <1> 	; 23/06/2015
  4355 00004C93 8B2D[78700000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4356                              <1> 	;and	ebp, ebp
  4357                              <1> 	;jz	short sysbreak_3 
  4358                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4359                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4360 00004C99 8B15[44700000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4361 00004C9F 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4362                              <1> 	; 07/10/2015
  4363 00004CA2 891D[78700000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4364                              <1> 	;
  4365 00004CA8 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4366                              <1> 			   ; with top of user's stack (virtual!)
  4367 00004CAA 7327                <1> 	jnb	short sysbreak_3
  4368                              <1> 		; cmp r1,sp / is it the same or higher 
  4369                              <1> 			  ; / than the stack?
  4370                              <1> 		; bhis 1f / yes, 1f
  4371 00004CAC 89DE                <1> 	mov	esi, ebx
  4372 00004CAE 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4373 00004CB0 7621                <1> 	jna	short sysbreak_3 
  4374                              <1> 	;push	ebx
  4375                              <1> sysbreak_1:
  4376 00004CB2 89EB                <1> 	mov	ebx, ebp  
  4377 00004CB4 E8E1E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4378 00004CB9 0F82ABFEFFFF        <1> 	jc	tr_addr_nm_err
  4379                              <1> 	; 18/10/2015
  4380 00004CBF 89C7                <1> 	mov	edi, eax 
  4381 00004CC1 29C0                <1> 	sub	eax, eax ; 0
  4382                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4383 00004CC3 39CE                <1> 	cmp	esi, ecx
  4384 00004CC5 7302                <1> 	jnb	short sysbreak_2
  4385 00004CC7 89F1                <1> 	mov	ecx, esi
  4386                              <1> sysbreak_2:
  4387 00004CC9 29CE                <1> 	sub	esi, ecx
  4388 00004CCB 01CD                <1> 	add	ebp, ecx
  4389 00004CCD F3AA                <1> 	rep 	stosb
  4390 00004CCF 09F6                <1> 	or	esi, esi
  4391 00004CD1 75DF                <1> 	jnz	short sysbreak_1
  4392                              <1> 	;
  4393                              <1> 		; bit $1,r1 / is it an odd address
  4394                              <1> 		; beq 2f / no, its even
  4395                              <1> 		; clrb (r1)+ / yes, make it even
  4396                              <1> 	; 2: / clear area between the break point and the stack
  4397                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4398                              <1> 		; bhis 1f / yes, quit
  4399                              <1> 		; clr (r1)+ / clear word
  4400                              <1> 		; br 2b / go back
  4401                              <1> 	;pop	ebx
  4402                              <1> sysbreak_3: ; 1:
  4403                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4404                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4405                              <1> 			; / in u.break (set new break point)
  4406                              <1> 		; br sysret4 / br sysret
  4407 00004CD3 E907EEFFFF          <1> 	jmp	sysret
  4408                              <1> 
  4409                              <1> maknod: 
  4410                              <1> 	; 11/02/2022
  4411                              <1> 	; 09/01/2022
  4412                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4413                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4414                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4415                              <1> 	;
  4416                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4417                              <1> 	; for this i-node in the current directory.
  4418                              <1> 	;
  4419                              <1> 	; INPUTS ->
  4420                              <1> 	;    r1 - contains mode
  4421                              <1> 	;    ii - current directory's i-number	
  4422                              <1> 	;    	
  4423                              <1> 	; OUTPUTS ->
  4424                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4425                              <1> 	;    i.flgs - flags in new i-node 
  4426                              <1> 	;    i.uid - filled with u.uid
  4427                              <1> 	;    i.nlks - 1 is put in the number of links
  4428                              <1> 	;    i.ctim - creation time				
  4429                              <1> 	;    i.ctim+2 - modification time
  4430                              <1> 	;    imod - set via call to setimod
  4431                              <1> 	;	
  4432                              <1> 	; ((AX = R1)) input
  4433                              <1> 	;
  4434                              <1> 	; (Retro UNIX Prototype : 
  4435                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4436                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4437                              <1> 
  4438                              <1> 	; / r1 contains the mode
  4439 00004CD8 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4440                              <1> 		; bis $100000,r1 / allocate flag set
  4441 00004CDB 6650                <1> 	push	ax ; * ; 24/12/2021
  4442                              <1> 		; mov r1,-(sp) / put mode on stack
  4443                              <1> 	; 31/07/2013
  4444 00004CDD 66A1[2C700000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4445                              <1> 		; mov ii,r1 / move current i-number to r1
  4446 00004CE3 B201                <1> 	mov	dl, 1 ; owner flag mask
  4447 00004CE5 E8C6050000          <1> 	call	access	
  4448                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4449 00004CEA 50                  <1> 	push	eax ; ** ; 24/12/2021
  4450                              <1> 		; mov r1,-(sp) / put i-number on stack
  4451 00004CEB 66B82800            <1> 	mov	ax, 40
  4452                              <1> 		; mov $40.,r1 / r1 = 40
  4453                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4454 00004CEF 6640                <1> 	inc	ax
  4455                              <1> 		; inc r1 / r1 = r1 + 1
  4456 00004CF1 E87F060000          <1> 	call	imap
  4457                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4458                              <1> 			    ; /	inode map in r2 & m
  4459                              <1>   
  4460                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4461                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4462                              <1> 
  4463                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4464                              <1> 	;	       Inode count must be checked here
  4465                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4466                              <1> 
  4467                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4468                              <1> 	; (inode count check)
  4469                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4470                              <1> 
  4471 00004CF6 730F                <1> 	jnc	short maknod2
  4472                              <1> 
  4473                              <1> 	; no free inode in inode table !
  4474 00004CF8 C705[A1700000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4474 00004D00 0000                <1>
  4475                              <1> 			; miscellaneous/other errors
  4476 00004D02 E9B8EDFFFF          <1> 	jmp	error	
  4477                              <1> maknod2: 
  4478 00004D07 8413                <1> 	test	[ebx], dl
  4479                              <1> 		; bitb mq,(r2) / is the i-node active
  4480 00004D09 75E4                <1> 	jnz	short maknod1
  4481                              <1> 		; bne 1b / yes, try the next one
  4482 00004D0B 0813                <1> 	or	[ebx], dl
  4483                              <1> 		; bisb mq,(r2) / no, make it active 
  4484                              <1> 			     ; / (put a 1 in the bit map)
  4485 00004D0D E8CA040000          <1> 	call	iget
  4486                              <1> 		; jsr r0,iget / get i-node into core
  4487                              <1> 	; 09/01/2022
  4488 00004D12 F605[496D0000]80    <1> 	test	byte [i.flgs+1], 80h
  4489                              <1> 	;test	word [i.flgs], 8000h 
  4490                              <1> 		; tst i.flgs / is i-node already allocated
  4491 00004D19 75D4                <1> 	jnz	short maknod1	
  4492                              <1> 		; blt 1b / yes, look for another one
  4493 00004D1B 66A3[7E700000]      <1> 	mov	[u.dirbuf], ax
  4494                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4495 00004D21 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4496                              <1> 		; mov (sp)+,r1 / get current i-number back
  4497 00004D22 E8B5040000          <1> 	call	iget
  4498                              <1> 		; jsr r0,iget / get i-node in core
  4499 00004D27 E857F7FFFF          <1> 	call	mkdir
  4500                              <1> 		; jsr r0,mkdir / make a directory entry 
  4501                              <1> 			     ; / in current directory
  4502 00004D2C 66A1[7E700000]      <1> 	mov	ax, [u.dirbuf]
  4503                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4504 00004D32 E8A5040000          <1> 	call	iget
  4505                              <1> 		; jsr r0,iget / get it into core
  4506                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4507                              <1> 	;mov	ecx, 8
  4508                              <1> 	; 09/01/2022 
  4509 00004D37 29C9                <1> 	sub	ecx, ecx
  4510 00004D39 B108                <1> 	mov	cl, 8
  4511 00004D3B 31C0                <1> 	xor	eax, eax ; 0
  4512 00004D3D BF[486D0000]        <1> 	mov	edi, inode 
  4513 00004D42 F3AB                <1> 	rep	stosd
  4514                              <1> 	;
  4515 00004D44 668F05[486D0000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4516                              <1> 		; mov (sp)+,i.flgs / fill flags
  4517 00004D4B 8A0D[98700000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4518 00004D51 880D[4B6D0000]      <1> 	mov 	[i.uid], cl
  4519                              <1> 		; movb u.uid,i.uid / user id	
  4520 00004D57 C605[4A6D0000]01    <1> 	mov     byte [i.nlks], 1
  4521                              <1> 		; movb $1,i.nlks / 1 link
  4522                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4523                              <1> 	;mov	eax, [s.time]
  4524                              <1> 	;mov 	[i.ctim], eax
  4525                              <1> 	 	; mov s.time,i.ctim / time created
  4526                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4527                              <1> 	; Retro UNIX 8086 v1 modification !
  4528                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4529                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4530                              <1> 	;call	setimod
  4531                              <1> 	;	; jsr r0,setimod / set modified flag
  4532                              <1> 	;retn
  4533                              <1> 	;	; rts r0 / return
  4534                              <1> 	; 24/12/2021
  4535 00004D5E E983050000          <1> 	jmp	setimod
  4536                              <1> 
  4537                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4538                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4539                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4540                              <1> 	;
  4541                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4542                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4543                              <1> 	; The file descriptor refers to a file open for reading or
  4544                              <1> 	; writing. The read (or write) pointer is set as follows:
  4545                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4546                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4547                              <1> 	;	  current location plus offset.
  4548                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4549                              <1> 	;	  size of file plus offset.
  4550                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4551                              <1> 	;
  4552                              <1> 	; Calling sequence:
  4553                              <1> 	;	sysseek; offset; ptrname
  4554                              <1> 	; Arguments:
  4555                              <1> 	;	offset - number of bytes desired to move 
  4556                              <1> 	;		 the r/w pointer
  4557                              <1> 	;	ptrname - a switch indicated above
  4558                              <1> 	;
  4559                              <1> 	; Inputs: r0 - file descriptor 
  4560                              <1> 	; Outputs: -
  4561                              <1> 	; ...............................................................
  4562                              <1> 	;	
  4563                              <1> 	; Retro UNIX 8086 v1 modification: 
  4564                              <1> 	;       'sysseek' system call has three arguments; so,
  4565                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4566                              <1> 	;	* 2nd argument, offset is in CX register
  4567                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4568                              <1> 	;	
  4569                              <1> 
  4570 00004D63 E822000000          <1> 	call	seektell
  4571                              <1> 	; AX = u.count
  4572                              <1> 	; BX = *u.fofp
  4573                              <1> 		; jsr r0,seektell / get proper value in u.count
  4574                              <1> 		; add u.base,u.count / add u.base to it
  4575 00004D68 0305[6C700000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4576 00004D6E 8903                <1> 	mov	[ebx], eax
  4577                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4578 00004D70 E96AEDFFFF          <1> 	jmp	sysret
  4579                              <1> 		; br sysret4
  4580                              <1> 
  4581                              <1> systell: ; / get the r/w pointer
  4582                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4583                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4584                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4585                              <1> 	;
  4586                              <1> 	; Retro UNIX 8086 v1 modification:
  4587                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4588                              <1> 	; 	    it returns with error !
  4589                              <1> 	; Inputs: r0 - file descriptor 
  4590                              <1> 	; Outputs: r0 - file r/w pointer
  4591                              <1> 
  4592                              <1> 	;xor	ecx, ecx ; 0
  4593                              <1> 	;mov	edx, 1 ; 05/08/2013
  4594                              <1> 	; 24/12/2021
  4595 00004D75 29D2                <1> 	sub	edx, edx
  4596 00004D77 FEC2                <1> 	inc	dl
  4597                              <1> 	; edx = 1
  4598                              <1> 	;call 	seektell
  4599 00004D79 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4600                              <1> 	;mov	ebx, [u.fofp]
  4601 00004D7E 8B03                <1> 	mov	eax, [ebx]
  4602 00004D80 A3[4C700000]        <1> 	mov	[u.r0], eax
  4603 00004D85 E955EDFFFF          <1> 	jmp	sysret
  4604                              <1> 
  4605                              <1> ; Original unix v1 'systell' system call:
  4606                              <1> 		; jsr r0,seektell
  4607                              <1> 		; br error4
  4608                              <1> 
  4609                              <1> seektell:
  4610                              <1> 	; 03/02/2022
  4611                              <1> 	; 03/01/2016
  4612                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4613                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4614                              <1> 	;
  4615                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4616                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4617                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4618                              <1> 	; getf. The i-node is brought into core and then u.count
  4619                              <1> 	; is checked to see it is a 0, 1, or 2.
  4620                              <1> 	; If it is 0 - u.count stays the same
  4621                              <1> 	;          1 - u.count = offset (u.fofp)
  4622                              <1> 	;	   2 - u.count = i.size (size of file)
  4623                              <1> 	; 	 		
  4624                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4625                              <1> 	;	Argument 1, file descriptor is in BX;
  4626                              <1> 	;	Argument 2, offset is in CX;
  4627                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4628                              <1> 	;
  4629                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4630                              <1> 	; call 	arg
  4631                              <1> 	;
  4632                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4633                              <1> 	;
  4634 00004D8A 890D[6C700000]      <1> 	mov 	[u.base], ecx ; offset
  4635                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4636                              <1> seektell0:
  4637 00004D90 8915[70700000]      <1> 	mov 	[u.count], edx
  4638                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4639                              <1> 	; mov	ax, bx
  4640                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4641                              <1> 			     ; / (index in u.fp list)
  4642                              <1> 	; call	getf
  4643                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4644                              <1> 	; BX = file descriptor (file number)
  4645 00004D96 E800FCFFFF          <1> 	call	getf1
  4646                              <1> 	; 03/02/2022
  4647 00004D9B 09C0                <1> 	or	eax, eax
  4648                              <1> 	;or	ax, ax ; i-number of the file
  4649                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4650                              <1> 		             ; / put it on the stack
  4651                              <1> 	;jz	error
  4652                              <1> 		; beq error4 / if i-number is 0, not active so error
  4653 00004D9D 750F                <1> 	jnz	short seektell1
  4654 00004D9F C705[A1700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4654 00004DA7 0000                <1>
  4655 00004DA9 E911EDFFFF          <1> 	jmp	error
  4656                              <1> seektell1:
  4657                              <1> 	;push	eax
  4658 00004DAE 80FC80              <1> 	cmp	ah, 80h
  4659 00004DB1 7203                <1> 	jb	short seektell2
  4660                              <1> 		; bgt .+4 / if its positive jump
  4661 00004DB3 66F7D8              <1> 	neg	ax
  4662                              <1> 		; neg r1 / if not make it positive
  4663                              <1> seektell2:
  4664 00004DB6 E821040000          <1> 	call	iget
  4665                              <1> 		; jsr r0,iget / get its i-node into core
  4666 00004DBB 8B1D[5C700000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4667 00004DC1 803D[70700000]01    <1> 	cmp	byte [u.count], 1
  4668                              <1> 		; cmp u.count,$1 / is ptr name =1
  4669 00004DC8 7705                <1> 	ja	short seektell3
  4670                              <1> 		; blt 2f / no its zero
  4671 00004DCA 740A                <1> 	je	short seektell_4
  4672                              <1> 		; beq 1f / yes its 1
  4673 00004DCC 31C0                <1> 	xor	eax, eax
  4674                              <1> 	;jmp	short seektell_5
  4675 00004DCE C3                  <1> 	retn
  4676                              <1> seektell3:
  4677                              <1> 	; 03/01/2016
  4678                              <1> 	;movzx	eax, word [i.size]
  4679 00004DCF 66A1[4C6D0000]      <1>         mov   	ax, [i.size]
  4680                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4681                              <1>                                    ; / in file in u.count
  4682                              <1> 	;jmp	short seektell_5
  4683                              <1> 		; br 2f
  4684 00004DD5 C3                  <1> 	retn
  4685                              <1> seektell_4: ; 1: / ptrname =1
  4686                              <1> 	;mov	ebx, [u.fofp]
  4687 00004DD6 8B03                <1> 	mov	eax, [ebx]
  4688                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4689                              <1> ;seektell_5: ; 2: / ptrname =0
  4690                              <1> 	;mov	[u.count], eax
  4691                              <1> 	;pop	eax 
  4692                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4693 00004DD8 C3                  <1> 	retn
  4694                              <1> 		; rts r0
  4695                              <1> 
  4696                              <1> sysintr: ; / set interrupt handling
  4697                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4698                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4699                              <1> 	;
  4700                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4701                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4702                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4703                              <1> 	; If one does the interrupt character in the tty buffer is
  4704                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4705                              <1> 	; 'sysret' is just called.	
  4706                              <1> 	;
  4707                              <1> 	; Calling sequence:
  4708                              <1> 	;	sysintr; arg
  4709                              <1> 	; Argument:
  4710                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4711                              <1> 	;	    - if 1, intterupts cause their normal result
  4712                              <1> 	;		 i.e force an exit.
  4713                              <1> 	;	    - if arg is a location within the program,
  4714                              <1> 	;		control is passed to that location when
  4715                              <1> 	;		an interrupt occurs.	
  4716                              <1> 	; Inputs: -
  4717                              <1> 	; Outputs: -
  4718                              <1> 	; ...............................................................
  4719                              <1> 	;	
  4720                              <1> 	; Retro UNIX 8086 v1 modification: 
  4721                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4722                              <1> 	;	then branches into sysquit.
  4723                              <1> 	;
  4724 00004DD9 66891D[90700000]    <1> 	mov	[u.intr], bx
  4725                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4726                              <1> 		; br 1f / go into quit routine
  4727 00004DE0 E9FAECFFFF          <1> 	jmp	sysret
  4728                              <1> 
  4729                              <1> sysquit:
  4730                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4731                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4732                              <1> 	;
  4733                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4734                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4735                              <1> 	; tty exists. If one does the interrupt character in the tty
  4736                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4737                              <1> 	; 'sysret' is just called.	
  4738                              <1> 	;
  4739                              <1> 	; Calling sequence:
  4740                              <1> 	;	sysquit; arg
  4741                              <1> 	; Argument:
  4742                              <1> 	;	arg - if 0, this call diables quit signals from the
  4743                              <1> 	;		typewriter (ASCII FS)
  4744                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4745                              <1> 	;		cease and a core image to be produced.
  4746                              <1> 	;		 i.e force an exit.
  4747                              <1> 	;	    - if arg is an addres in the program,
  4748                              <1> 	;		a quit causes control to sent to that
  4749                              <1> 	;		location.	
  4750                              <1> 	; Inputs: -
  4751                              <1> 	; Outputs: -
  4752                              <1> 	; ...............................................................
  4753                              <1> 	;	
  4754                              <1> 	; Retro UNIX 8086 v1 modification: 
  4755                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4756                              <1> 	;	then branches into 'sysret'.
  4757                              <1> 	;
  4758 00004DE5 66891D[92700000]    <1> 	mov	[u.quit], bx
  4759 00004DEC E9EEECFFFF          <1> 	jmp	sysret
  4760                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4761                              <1> 	;1:
  4762                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4763                              <1> 			      ; / to r1
  4764                              <1> 		; beq sysret4 / return to user
  4765                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4766                              <1> 			   ; / in the tty buffer
  4767                              <1> 		; br sysret4 / return to user
  4768                              <1> 
  4769                              <1> syssetuid: ; / set process id
  4770                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4771                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4772                              <1> 	;
  4773                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4774                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4775                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4776                              <1> 	; Only the super user can make this call.	
  4777                              <1> 	;
  4778                              <1> 	; Calling sequence:
  4779                              <1> 	;	syssetuid
  4780                              <1> 	; Arguments: -
  4781                              <1> 	;
  4782                              <1> 	; Inputs: (u.r0) - contains the process id.
  4783                              <1> 	; Outputs: -
  4784                              <1> 	; ...............................................................
  4785                              <1> 	;	
  4786                              <1> 	; Retro UNIX 8086 v1 modification: 
  4787                              <1> 	;       BL contains the (new) user ID of the current process
  4788                              <1> 
  4789                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4790 00004DF1 3A1D[99700000]      <1> 	cmp	bl, [u.ruid] 
  4791                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4792                              <1> 			       ; / id number
  4793 00004DF7 741E                <1> 	je	short setuid1
  4794                              <1> 		; beq 1f / yes
  4795 00004DF9 803D[98700000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4796                              <1> 		; tstb u.uid / no, is current user the super user?
  4797                              <1> 	;ja	error
  4798                              <1> 		; bne error4 / no, error
  4799 00004E00 760F                <1> 	jna	short setuid0
  4800 00004E02 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4800 00004E0A 0000                <1>
  4801                              <1> 				; 'permission denied !' error
  4802 00004E0C E9AEECFFFF          <1> 	jmp	error
  4803                              <1> setuid0:
  4804 00004E11 881D[99700000]      <1> 	mov	[u.ruid], bl
  4805                              <1> setuid1: ; 1:
  4806 00004E17 881D[98700000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4807                              <1> 		; movb r1,u.uid / put process id in u.uid
  4808                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4809 00004E1D E9BDECFFFF          <1> 	jmp	sysret
  4810                              <1> 		; br sysret4 / system return
  4811                              <1> 
  4812                              <1> sysgetuid: ; < get user id >
  4813                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4814                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4815                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4816                              <1> 	;
  4817                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4818                              <1> 	; The real user ID identifies the person who is logged in,
  4819                              <1> 	; in contradistinction to the effective user ID, which
  4820                              <1> 	; determines his access permission at each moment. It is thus
  4821                              <1> 	; useful to programs which operate using the 'set user ID'
  4822                              <1> 	; mode, to find out who invoked them.	
  4823                              <1> 	;
  4824                              <1> 	; Calling sequence:
  4825                              <1> 	;	syssetuid
  4826                              <1> 	; Arguments: -
  4827                              <1> 	;
  4828                              <1> 	; Inputs: -
  4829                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4830                              <1> 	; ...............................................................
  4831                              <1> 	;	
  4832                              <1> 	; Retro UNIX 8086 v1 modification: 
  4833                              <1> 	;       AL contains the real user ID at return.
  4834                              <1> 	;
  4835                              <1> 	;movzx 	eax, byte [u.ruid]
  4836                              <1> 	; 09/01/2022
  4837 00004E22 A0[99700000]        <1> 	mov	al, [u.ruid]
  4838 00004E27 A3[4C700000]        <1> 	mov	[u.r0], eax
  4839                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4840 00004E2C E9AEECFFFF          <1> 	jmp	sysret
  4841                              <1> 		; br sysret4 / systerm return, sysret
  4842                              <1> 
  4843                              <1> anyi: 
  4844                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4845                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4846                              <1> 	;
  4847                              <1> 	; 'anyi' is called if a file deleted while open.
  4848                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4849                              <1> 	;
  4850                              <1> 	; INPUTS ->
  4851                              <1> 	;    r1 - contains an i-number
  4852                              <1> 	;    fsp - start of table containing open files
  4853                              <1> 	;
  4854                              <1> 	; OUTPUTS ->
  4855                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4856                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4857                              <1> 	;    if file not found - bit in i-node map is cleared
  4858                              <1> 	;    			 (i-node is freed)
  4859                              <1> 	;               all blocks related to i-node are freed
  4860                              <1> 	;	        all flags in i-node are cleared
  4861                              <1> 	; ((AX = R1)) input
  4862                              <1> 	;
  4863                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4864                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4865                              <1> 	;
  4866                              <1> 		; / r1 contains an i-number
  4867 00004E31 BB[186E0000]        <1> 	mov	ebx, fsp
  4868                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4869                              <1> anyi_1: ; 1:
  4870 00004E36 663B03              <1> 	cmp	ax, [ebx]
  4871                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4872 00004E39 7433                <1> 	je	short anyi_3
  4873                              <1> 		; beq 1f / yes, 1f
  4874 00004E3B 66F7D8              <1> 	neg	ax
  4875                              <1> 		; neg r1 / no complement r1
  4876 00004E3E 663B03              <1> 	cmp	ax, [ebx]
  4877                              <1> 		; cmp r1,(r2) / do they match now?
  4878 00004E41 742B                <1> 	je	short anyi_3
  4879                              <1> 		; beq 1f / yes, transfer
  4880                              <1> 		; / i-numbers do not match
  4881 00004E43 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4882                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4883                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4884 00004E46 81FB[0C700000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4885                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4886                              <1> 				; / are we at last entry in the table
  4887 00004E4C 72E8                <1> 	jb	short anyi_1
  4888                              <1> 		; blt 1b / no, check next entries i-number
  4889                              <1> 	;cmp	ax, 32768
  4890 00004E4E 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4891                              <1> 		; tst r1 / yes, no match
  4892                              <1> 		; bge .+4
  4893 00004E51 7203                <1> 	jb	short anyi_2
  4894 00004E53 66F7D8              <1> 	neg	ax
  4895                              <1> 		; neg r1 / make i-number positive
  4896                              <1> anyi_2:	
  4897 00004E56 E81A050000          <1> 	call	imap
  4898                              <1> 		; jsr r0,imap / get address of allocation bit 
  4899                              <1> 			    ; / in the i-map in r2
  4900                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4901                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4902                              <1>  	; not	dx
  4903 00004E5B F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4904                              <1>         ;and	[ebx], dx
  4905 00004E5D 2013                <1> 	and 	[ebx], dl 
  4906                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4907 00004E5F E8A4040000          <1> 	call	itrunc
  4908                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4909 00004E64 66C705[486D0000]00- <1>  	mov 	word [i.flgs], 0
  4909 00004E6C 00                  <1>
  4910                              <1> 		; clr i.flgs / clear all flags in the i-node
  4911 00004E6D C3                  <1> 	retn
  4912                              <1> 		;rts	r0 / return
  4913                              <1> anyi_3: ; 1: / i-numbers match
  4914 00004E6E FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4915                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4916                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4917 00004E71 C3                  <1> 	retn
  4918                              <1> 		; rts r0
  2104                                  %include 'u3.s'        ; 10/05/2015
  2105                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2106                              <1> ; Last Modification: 24/12/2021
  2107                              <1> ; ----------------------------------------------------------------------------
  2108                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2109                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2110                              <1> ;
  2111                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2112                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2113                              <1> ; <Bell Laboratories (17/3/1972)>
  2114                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2115                              <1> ;
  2116                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2117                              <1> ;
  2118                              <1> ; ****************************************************************************
  2119                              <1> 
  2120                              <1> tswitch: ; Retro UNIX 386 v1
  2121                              <1> tswap:
  2122                              <1> 	; 01/09/2015
  2123                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2124                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2125                              <1> 	; time out swap, called when a user times out.
  2126                              <1> 	; the user is put on the low priority queue.
  2127                              <1> 	; This is done by making a link from the last user
  2128                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2129                              <1> 	; then he is swapped out.
  2130                              <1> 	;
  2131                              <1> 	; Retro UNIX 386 v1 modification ->
  2132                              <1> 	;       swap (software task switch) is performed by changing
  2133                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2134                              <1> 	;	as in Retro UNIX 8086 v1.
  2135                              <1> 	;
  2136                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2137                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2138                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2139                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2140                              <1> 	;	compatibles was using 1MB segmented memory 
  2141                              <1> 	;	in 8086/8088 times.
  2142                              <1> 	;
  2143                              <1> 	; INPUTS ->
  2144                              <1> 	;    u.uno - users process number
  2145                              <1> 	;    runq+4 - lowest priority queue
  2146                              <1> 	; OUTPUTS ->
  2147                              <1> 	;    r0 - users process number
  2148                              <1> 	;    r2 - lowest priority queue address
  2149                              <1> 	;
  2150                              <1> 	; ((AX = R0, BX = R2)) output
  2151                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2152                              <1> 	;
  2153 00004E72 A0[9B700000]        <1> 	mov 	al, [u.uno]
  2154                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2155                              <1> 		; mov  $runq+4,r2 
  2156                              <1> 			; / move lowest priority queue address to r2
  2157 00004E77 E8CD000000          <1>         call 	putlu
  2158                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2159                              <1> 		             ; / u.uno's user
  2160                              <1> 
  2161                              <1> switch: ; Retro UNIX 386 v1
  2162                              <1> swap:
  2163                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2164                              <1> 	; 02/09/2015
  2165                              <1> 	; 01/09/2015
  2166                              <1> 	; 31/08/2015
  2167                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2168                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2169                              <1> 	; 'swap' is routine that controls the swapping of processes
  2170                              <1> 	; in and out of core.
  2171                              <1> 	;
  2172                              <1> 	; Retro UNIX 386 v1 modification ->
  2173                              <1> 	;       swap (software task switch) is performed by changing
  2174                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2175                              <1> 	;	as in Retro UNIX 8086 v1.
  2176                              <1> 	;
  2177                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2178                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2179                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2180                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2181                              <1> 	;	compatibles was using 1MB segmented memory 
  2182                              <1> 	;	in 8086/8088 times.
  2183                              <1> 	;
  2184                              <1> 	; INPUTS ->
  2185                              <1> 	;    runq table - contains processes to run.
  2186                              <1> 	;    p.link - contains next process in line to be run.
  2187                              <1> 	;    u.uno - process number of process in core	
  2188                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2189                              <1> 	; OUTPUTS ->
  2190                              <1> 	;    (original unix v1 -> present process to its disk block)
  2191                              <1> 	;    (original unix v1 -> new process into core -> 
  2192                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2193                              <1> 	;	   for new process)
  2194                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2195                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2196                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2197                              <1> 	;	 for now, it will swap the process if there is not
  2198                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2199                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2200                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2201                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2202                              <1> 	;
  2203                              <1> 	;    u.pri -points to highest priority run Q.
  2204                              <1> 	;    r2 - points to the run queue.
  2205                              <1> 	;    r1 - contains new process number
  2206                              <1> 	;    r0 - points to place in routine or process that called
  2207                              <1> 	;	  swap all user parameters
  2208                              <1> 	;				
  2209                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2210                              <1> 	;
  2211                              <1> swap_0:
  2212                              <1> 		;mov $300,*$ps / processor priority = 6
  2213 00004E7C BE[3C700000]        <1> 	mov	esi, runq
  2214                              <1> 		; mov $runq,r2 / r2 points to runq table
  2215                              <1> swap_1: ; 1: / search runq table for highest priority process
  2216 00004E81 668B06              <1> 	mov	ax, [esi]
  2217 00004E84 6621C0              <1> 	and 	ax, ax
  2218                              <1>        		; tst (r2)+ / are there any processes to run 
  2219                              <1> 			  ; / in this Q entry
  2220 00004E87 7507                <1> 	jnz	short swap_2
  2221                              <1>        		; bne 1f / yes, process 1f
  2222                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2223                              <1> 			       ; / to end of table
  2224                              <1> 		; bne 1b / if not at end, go back
  2225 00004E89 E8E0000000          <1> 	call	idle
  2226                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2227                              <1> 				       ; / all queues are empty
  2228 00004E8E EBF1                <1> 	jmp	short swap_1
  2229                              <1> 		; br swap
  2230                              <1> swap_2: ; 1:
  2231 00004E90 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2232                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2233                              <1>  		; mov r2,u.pri / set present user to this run queue
  2234                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2235 00004E93 38E0                <1> 	cmp	al, ah
  2236                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2237                              <1> 			      ; / in this Q to be run
  2238 00004E95 740A                <1> 	je	short swap_3
  2239                              <1>        		; beq 1f / yes
  2240                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2241                              <1> 	;movzx	ebx, al
  2242 00004E97 8AA3[B76D0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2243 00004E9D 8826                <1>        	mov	[esi], ah
  2244                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2245                              <1> 				       ; / in line into run queue
  2246 00004E9F EB05                <1> 	jmp	short swap_4
  2247                              <1>        		; br 2f
  2248                              <1> swap_3: ; 1:
  2249                              <1> 	;xor	dx, dx
  2250                              <1> 	; 24/12/2021
  2251 00004EA1 31D2                <1> 	xor	edx, edx
  2252 00004EA3 668916              <1> 	mov	[esi], dx
  2253                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2254                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2255                              <1>       ; / in new process if required
  2256                              <1>        		; clr *$ps / clear processor status
  2257 00004EA6 8A25[9B700000]      <1> 	mov 	ah, [u.uno]
  2258 00004EAC 38C4                <1> 	cmp	ah, al
  2259                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2260                              <1> 			      ; / the process in core?
  2261 00004EAE 743B                <1>        	je	short swap_8
  2262                              <1>        		; beq 2f / yes, don't have to swap
  2263                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2264                              <1> 			   ; / (address in routine that called swap)
  2265                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2266                              <1> 	; 01/09/2015
  2267                              <1> 	;mov	[u.usp], esp
  2268                              <1>        		; mov sp,u.usp / save stack pointer
  2269                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2270                              <1> 			       ; / to the stack pointer
  2271 00004EB0 08E4                <1> 	or	ah, ah
  2272                              <1>        		; tstb u.uno / is the process # = 0
  2273 00004EB2 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2274                              <1> 		; beq 1f / yes, kill process by overwriting
  2275                              <1> 	; 02/09/2015
  2276 00004EB4 8925[48700000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2277                              <1> 	;
  2278 00004EBA E834000000          <1> 	call	wswap
  2279                              <1> 		; jsr r0,wswap / write out core to disk
  2280                              <1> 	 ; 31/08/2015
  2281                              <1> 	;movzx	ebx, al ; New (running) process number
  2282 00004EBF EB1C                <1> 	jmp 	short swap_7
  2283                              <1> swap_6:
  2284                              <1> 	; 31/08/2015
  2285                              <1> 	; Deallocate memory pages belong to the process
  2286                              <1> 	; which is being terminated
  2287                              <1> 	; 14/05/2015 ('sysexit')
  2288                              <1>  	; Deallocate memory pages of the process
  2289                              <1> 	; (Retro UNIX 386 v1 modification !)
  2290                              <1> 	;
  2291                              <1> 	; movzx ebx, al
  2292 00004EC1 53                  <1> 	push	ebx
  2293 00004EC2 A1[A5700000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2294 00004EC7 8B1D[A9700000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2295 00004ECD E80CE0FFFF          <1> 	call	deallocate_page_dir
  2296 00004ED2 A1[9C700000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2297 00004ED7 E89AE0FFFF          <1> 	call	deallocate_page
  2298 00004EDC 5B                  <1> 	pop	ebx
  2299                              <1> swap_7: ;1: 
  2300                              <1> 	; 02/09/2015
  2301                              <1> 	; 31/08/2015
  2302                              <1> 	; 14/05/2015
  2303 00004EDD C0E302              <1> 	shl	bl, 2 ; * 4 
  2304 00004EE0 8B83[D46D0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2305                              <1> 	;cli
  2306 00004EE6 E831000000          <1> 	call	rswap
  2307                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2308                              <1> 		; jsr r0,rswap / read new process into core
  2309                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2310                              <1> 			      ; / to his program to its normal
  2311                              <1> 	; 01/09/2015
  2312                              <1> 	;mov	esp, [u.usp]	
  2313                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2314                              <1> 			     ; / new process stack
  2315                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2316                              <1> 			     ; / that just got swapped in, left off.,
  2317                              <1> 			     ; / i.e., transfer control to new process
  2318                              <1> 	;sti
  2319                              <1> swap_8: ;2:
  2320                              <1> 	; RETRO UNIX 8086 v1 modification !
  2321 00004EEB C605[8E700000]04    <1> 	mov	byte [u.quant], time_count 
  2322                              <1> 		; movb $30.,uquant / initialize process time quantum
  2323 00004EF2 C3                  <1> 	retn
  2324                              <1> 		; rts r0 / return
  2325                              <1> 
  2326                              <1> wswap:  ; < swap out, swap to disk >
  2327                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2328                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2329                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2330                              <1> 	; appropriate disk area.
  2331                              <1> 	;
  2332                              <1> 	; Retro UNIX 386 v1 modification ->
  2333                              <1> 	;       User (u) structure content and the user's register content
  2334                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2335                              <1> 	;	saving 'u' structure and user registers for task switching).
  2336                              <1> 	;	u.usp - points to kernel stack address which contains
  2337                              <1> 	;		user's registers while entering system call.  
  2338                              <1> 	;	u.sp  - points to kernel stack address 
  2339                              <1> 	;		to return from system call -for IRET-.
  2340                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2341                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2342                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2343                              <1> 	;
  2344                              <1> 	; Retro UNIX 8086 v1 modification ->
  2345                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2346                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2347                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2348                              <1> 	;	compatibles was using 1MB segmented memory 
  2349                              <1> 	;	in 8086/8088 times.
  2350                              <1> 	;
  2351                              <1> 	; INPUTS ->
  2352                              <1> 	;    u.break - points to end of program
  2353                              <1> 	;    u.usp - stack pointer at the moment of swap
  2354                              <1> 	;    core - beginning of process program		
  2355                              <1> 	;    ecore - end of core 	
  2356                              <1> 	;    user - start of user parameter area		
  2357                              <1> 	;    u.uno - user process number	
  2358                              <1> 	;    p.dska - holds block number of process	
  2359                              <1> 	; OUTPUTS ->
  2360                              <1> 	;    swp I/O queue
  2361                              <1> 	;    p.break - negative word count of process 
  2362                              <1> 	;    r1 - process disk address	
  2363                              <1> 	;    r2 - negative word count
  2364                              <1> 	;
  2365                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2366                              <1> 	;
  2367                              <1> 	; INPUTS ->
  2368                              <1> 	;    u.uno - process number (to be swapped out)
  2369                              <1> 	; OUTPUTS ->
  2370                              <1> 	;    none
  2371                              <1> 	;
  2372                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2373                              <1> 	;
  2374 00004EF3 8B3D[9C700000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2375 00004EF9 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2376 00004EFE BE[44700000]        <1> 	mov	esi, user ; active user (u) structure	
  2377 00004F03 F3A5                <1> 	rep	movsd
  2378                              <1> 	;
  2379 00004F05 8B35[48700000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2380                              <1> 			     ;      points to user registers)
  2381 00004F0B 8B0D[44700000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2382                              <1> 			     ; (for IRET)
  2383                              <1> 			     ; [u.sp] -> EIP (user)
  2384                              <1> 			     ; [u.sp+4]-> CS (user)
  2385                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2386                              <1> 			     ; [u.sp+12] -> ESP (user)
  2387                              <1> 			     ; [u.sp+16] -> SS (user)	
  2388 00004F11 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2389 00004F13 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2390                              <1> 			     ; (for IRET) 	
  2391 00004F16 C1E902              <1> 	shr	ecx, 2	     		
  2392 00004F19 F3A5                <1> 	rep	movsd
  2393 00004F1B C3                  <1> 	retn
  2394                              <1> 
  2395                              <1> 	; Original UNIX v1 'wswap' routine:
  2396                              <1> 	; wswap:
  2397                              <1> 		; mov *$30,u.emt / determines handling of emts
  2398                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2399                              <1> 				; / illegal instructions
  2400                              <1> 		; mov u.break,r2 / put process program break address in r2
  2401                              <1> 		; inc r2 / add 1 to it 
  2402                              <1> 		; bic $1,r2 / make it even
  2403                              <1> 		; mov r2,u.break / set break to an even location
  2404                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2405                              <1> 			     ; / at moment of swap in r3
  2406                              <1> 		; cmp r2,$core / is u.break less than $core
  2407                              <1> 		; blos 2f / yes
  2408                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2409                              <1>        		; bhis 2f / yes
  2410                              <1> 	; 1:
  2411                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2412                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2413                              <1> 		; bne 1b / no, keep packing
  2414                              <1> 	 	; br 1f / yes
  2415                              <1> 	; 2:
  2416                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2417                              <1> 	; 1:
  2418                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2419                              <1> 			   ; / (user up to end of stack gets written out)
  2420                              <1> 		; neg r2 / make it negative
  2421                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2422                              <1> 		; mov r2,swp+4 / word count
  2423                              <1> 		; movb u.uno,r1 / move user process number to r1
  2424                              <1> 		; asl r1 / x2 for index
  2425                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2426                              <1> 				     ; / into the p.break table
  2427                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2428                              <1> 				    ; /	for process to r1
  2429                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2430                              <1> 			     ; / (block number)
  2431                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2432                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2433                              <1> 	; 1:
  2434                              <1>        		; tstb swp+1 / is lt done writing?
  2435                              <1>        		; bne 1b / no, wait
  2436                              <1> 		; rts r0 / yes, return to swap
  2437                              <1> 
  2438                              <1> rswap:  ; < swap in, swap from disk >
  2439                              <1> 	; 15/09/2015
  2440                              <1> 	; 28/08/2015
  2441                              <1> 	; 14/05/2015
  2442                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2443                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2444                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2445                              <1> 	; from disk into core.
  2446                              <1> 	;
  2447                              <1> 	; Retro UNIX 386 v1 modification ->
  2448                              <1> 	;       User (u) structure content and the user's register content
  2449                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2450                              <1> 	;	saving 'u' structure and user registers for task switching).
  2451                              <1> 	;	u.usp - points to kernel stack address which contains
  2452                              <1> 	;		user's registers while entering system call.  
  2453                              <1> 	;	u.sp  - points to kernel stack address 
  2454                              <1> 	;		to return from system call -for IRET-.
  2455                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2456                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2457                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2458                              <1> 	;
  2459                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2460                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2461                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2462                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2463                              <1> 	;	compatibles was using 1MB segmented memory 
  2464                              <1> 	;	in 8086/8088 times.
  2465                              <1> 	;
  2466                              <1> 	; INPUTS ->
  2467                              <1> 	;    r1 - process number of process to be read in
  2468                              <1> 	;    p.break - negative of word count of process 
  2469                              <1> 	;    p.dska - disk address of the process		
  2470                              <1> 	;    u.emt - determines handling of emt's 	
  2471                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2472                              <1> 	; OUTPUTS ->
  2473                              <1> 	;    8 = (u.ilgins)
  2474                              <1> 	;    24 = (u.emt)
  2475                              <1> 	;    swp - bit 10 is set to indicate read 
  2476                              <1> 	;		(bit 15=0 when reading is done)	
  2477                              <1> 	;    swp+2 - disk block address
  2478                              <1> 	;    swp+4 - negative word count 	
  2479                              <1> 	;      ((swp+6 - address of user structure)) 
  2480                              <1> 	;
  2481                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2482                              <1> 	;
  2483                              <1> 	; INPUTS ->
  2484                              <1> 	;    AL	- new process number (to be swapped in)	 
  2485                              <1> 	; OUTPUTS ->
  2486                              <1> 	;    none
  2487                              <1> 	;
  2488                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2489                              <1> 	;
  2490                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2491 00004F1C 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2492 00004F1E B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2493 00004F23 BF[44700000]        <1> 	mov	edi, user ; active user (u) structure	
  2494 00004F28 F3A5                <1> 	rep	movsd
  2495 00004F2A 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2496 00004F2B 8B3D[48700000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2497                              <1> 			     ;      points to user registers)
  2498 00004F31 8B0D[44700000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2499                              <1> 			     ; (for IRET)
  2500                              <1> 			     ; [u.sp] -> EIP (user)
  2501                              <1> 			     ; [u.sp+4]-> CS (user)
  2502                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2503                              <1> 			     ; [u.sp+12] -> ESP (user)
  2504                              <1> 			     ; [u.sp+16] -> SS (user)		
  2505                              <1> 	; 28/08/2015
  2506 00004F37 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2507 00004F39 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2508                              <1> 			     ; (for IRET) 	
  2509 00004F3C C1E902              <1> 	shr	ecx, 2	       		
  2510 00004F3F F3A5                <1> 	rep	movsd
  2511 00004F41 8B25[48700000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2512 00004F47 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2513 00004F48 C3                  <1> 	retn
  2514                              <1> 
  2515                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2516                              <1> 	;rswap:
  2517                              <1>        		; asl r1 / process number x2 for index
  2518                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2519                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2520                              <1>        		; bis $2000,swp / read
  2521                              <1>        		; jsr r0,ppoke / read it in 
  2522                              <1> 	; 1:
  2523                              <1>        		; tstb swp+1 / done
  2524                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2525                              <1>        		; mov u.emt,*$30 / yes move these
  2526                              <1>        		; mov u.ilgins,*$10 / back
  2527                              <1>        		; rts r0 / return
  2528                              <1> 
  2529                              <1> 	;unpack: ; / move stack back to its normal place
  2530                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2531                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2532                              <1> 		; blos 2f / yes, return
  2533                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2534                              <1> 			     ; / before swapping
  2535                              <1> 		; bhis 2f / yes, return
  2536                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2537                              <1> 		; add r3,r2
  2538                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2539                              <1> 	; 1:
  2540                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2541                              <1> 		; cmp r2,u.break / in core
  2542                              <1> 		; bne 1b
  2543                              <1> 	; 2:
  2544                              <1>        		; rts r0
  2545                              <1> 
  2546                              <1> putlu: 
  2547                              <1> 	; 12/09/2015
  2548                              <1> 	; 02/09/2015
  2549                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2550                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2551                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2552                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2553                              <1> 	; the last process on the queue to process in r1 by putting
  2554                              <1> 	; the process number in r1 into the last process's link.
  2555                              <1> 	;
  2556                              <1> 	; INPUTS ->
  2557                              <1> 	;    r1 - user process number
  2558                              <1> 	;    r2 - points to lowest priority queue 
  2559                              <1> 	;    p.dska - disk address of the process		
  2560                              <1> 	;    u.emt - determines handling of emt's 	
  2561                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2562                              <1> 	; OUTPUTS ->
  2563                              <1> 	;    r3 - process number of last process on the queue upon
  2564                              <1> 	;	  entering putlu
  2565                              <1> 	;    p.link-1 + r3 - process number in r1
  2566                              <1> 	;    r2 - points to lowest priority queue
  2567                              <1> 	;
  2568                              <1> 	; ((Modified registers: EDX, EBX)) 
  2569                              <1> 	;
  2570                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2571                              <1> 
  2572                              <1> 	; eBX = r2
  2573                              <1> 	; eAX = r1 (AL=r1b)
  2574                              <1> 
  2575 00004F49 BB[3C700000]        <1> 	mov	ebx, runq
  2576 00004F4E 0FB613              <1> 	movzx  	edx, byte [ebx]
  2577 00004F51 43                  <1> 	inc	ebx
  2578 00004F52 20D2                <1> 	and	dl, dl
  2579                              <1> 		; tstb (r2)+ / is queue empty?
  2580 00004F54 740A                <1>        	jz	short putlu_1
  2581                              <1> 		; beq 1f / yes, branch
  2582 00004F56 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2583                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2584                              <1> 			     ; / in r3
  2585 00004F58 8882[B76D0000]      <1>        	mov	[edx+p.link-1], al
  2586                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2587                              <1> 			     ; / "last users" link
  2588 00004F5E EB03                <1> 	jmp	short putlu_2
  2589                              <1> 		; br 2f /
  2590                              <1> putlu_1: ; 1:
  2591 00004F60 8843FF              <1> 	mov	[ebx-1], al
  2592                              <1>        		; movb r1,-1(r2) / user is only user; 
  2593                              <1> 			    ; / put process no. at beginning and at end
  2594                              <1> putlu_2: ; 2: 
  2595 00004F63 8803                <1> 	mov	[ebx], al
  2596                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2597                              <1> 			     ; / on the queue
  2598 00004F65 88C2                <1> 	mov	dl, al
  2599 00004F67 88B2[B76D0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2600                              <1> 		; dec r2 / restore r2
  2601 00004F6D C3                  <1>         retn
  2602                              <1> 		; rts r0
  2603                              <1> 
  2604                              <1> ;copyz:
  2605                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2606                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2607                              <1> ;       mov     (r0)+,r1
  2608                              <1> ;       mov     (r0)+,r2
  2609                              <1> ;1:
  2610                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2611                              <1> ;       cmp     r1,r2 
  2612                              <1> ;       blo     1b
  2613                              <1> ;       mov     (sp)+,r2 / restore r2
  2614                              <1> ;       mov     (sp)+,r1 / restore r1
  2615                              <1> ;       rts     r0 
  2616                              <1> 
  2617                              <1> idle:
  2618                              <1> 	; 01/09/2015
  2619                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2620                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2621                              <1> 	; (idle & wait loop)
  2622                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2623                              <1> 	; idle procedure!
  2624                              <1>       	;
  2625                              <1>   	; 01/09/2015
  2626 00004F6E FB                  <1> 	sti
  2627                              <1>       	; 29/07/2013
  2628 00004F6F F4                  <1>       	hlt
  2629 00004F70 90                  <1>       	nop ; 10/10/2013
  2630 00004F71 90                  <1>       	nop
  2631 00004F72 90                  <1>       	nop
  2632                              <1>       	; 23/10/2013
  2633 00004F73 90                  <1>       	nop
  2634 00004F74 90                  <1>       	nop
  2635 00004F75 90                  <1>       	nop
  2636 00004F76 90                  <1>       	nop
  2637 00004F77 C3                  <1>       	retn      
  2638                              <1> 
  2639                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2640                              <1> 	;clr *$ps / clear ps
  2641                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2642                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2643                              <1> 	;1 / wait for interrupt
  2644                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2645                              <1> 	;mov (sp)+,*$ps
  2646                              <1> 	;rts r0
  2647                              <1> 
  2648                              <1> clear:
  2649                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2650                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2651                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2652                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2653                              <1> 	; on the current device (cdev)
  2654                              <1> 	;	
  2655                              <1> 	; INPUTS ->
  2656                              <1> 	;    r1 - block number of block to be zeroed
  2657                              <1> 	;    cdev - current device number 
  2658                              <1> 	; OUTPUTS ->
  2659                              <1> 	;    a zeroed I/O buffer onto the current device
  2660                              <1> 	;    r1 - points to last entry in the I/O buffer
  2661                              <1> 	;
  2662                              <1> 	; ((AX = R1)) input/output
  2663                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2664                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2665                              <1> 
  2666 00004F78 E8A20E0000          <1> 	call 	wslot
  2667                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2668                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2669 00004F7D 89DF                <1> 	mov	edi, ebx ; r5
  2670 00004F7F 89C2                <1> 	mov	edx, eax
  2671 00004F81 B980000000          <1> 	mov	ecx, 128
  2672                              <1> 		; mov $256.,r3
  2673 00004F86 31C0                <1> 	xor	eax, eax
  2674 00004F88 F3AB                <1> 	rep	stosd
  2675 00004F8A 89D0                <1> 	mov	eax, edx
  2676                              <1> ; 1: 
  2677                              <1>        		; clr (r5)+ / zero data word in buffer
  2678                              <1>        		; dec r3
  2679                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2680                              <1> 	;call	dskwr
  2681                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2682                              <1>                              ; / block specified in r1
  2683                              <1> 	; eAX (r1) = block number
  2684                              <1> 	;retn
  2685                              <1> 		; rts r0
  2686                              <1> 	; 24/12/2021
  2687 00004F8C E9AA0E0000          <1> 	jmp	dskwr
  2105                                  %include 'u4.s'        ; 15/04/2015
  2106                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2107                              <1> ; Last Modification: 26/02/2022
  2108                              <1> ; ----------------------------------------------------------------------------
  2109                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2110                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2111                              <1> ;
  2112                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2113                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2114                              <1> ; <Bell Laboratories (17/3/1972)>
  2115                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2116                              <1> ;
  2117                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2118                              <1> ;
  2119                              <1> ; ****************************************************************************
  2120                              <1> 
  2121                              <1> ;setisp:
  2122                              <1>        ;mov     r1,-(sp)
  2123                              <1>        ;mov     r2,-(sp)
  2124                              <1>        ;mov     r3,-(sp)
  2125                              <1>        ;mov     clockp,-(sp)
  2126                              <1>        ;mov     $s.syst+2,clockp
  2127                              <1>        ;jmp     (r0)
  2128                              <1> 
  2129                              <1> clock: ; / interrupt from 60 cycle clock
  2130                              <1> 	
  2131                              <1> 	; 14/10/2015
  2132                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2133                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2134                              <1> 
  2135                              <1>        ;mov     r0,-(sp) / save r0
  2136                              <1>        ;tst     *$lks / restart clock?
  2137                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2138                              <1>        ;inc     (r0)
  2139                              <1>        ;bne     1f
  2140                              <1>        ;inc     -(r0)
  2141                              <1> ;1:
  2142                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2143                              <1>        ;inc     (r0)
  2144                              <1>        ;bne     1f
  2145                              <1>        ;inc     -(r0)
  2146                              <1> ;1:
  2147                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2148                              <1> 
  2149 00004F91 803D[8E700000]00    <1> 	cmp	byte [u.quant], 0
  2150 00004F98 772C                <1> 	ja	short clk_1
  2151                              <1> 	;
  2152 00004F9A 803D[41700000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2153 00004FA1 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2154 00004FA3 803D[9B700000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2155 00004FAA 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2156 00004FAC 66833D[90700000]00  <1> 	cmp	word [u.intr], 0
  2157 00004FB4 7616                <1> 	jna	short clk_2
  2158                              <1> clk_0:
  2159                              <1> 	; 14/10/2015
  2160 00004FB6 FE05[41700000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2161 00004FBC 58                  <1> 	pop	eax ; return address to the timer interrupt
  2162                              <1> 	;
  2163 00004FBD B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2164                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2165 00004FBF E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2166                              <1> 	;
  2167 00004FC1 E97EEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2168                              <1> clk_1:
  2169 00004FC6 FE0D[8E700000]      <1> 	dec	byte [u.quant]
  2170                              <1> clk_2:
  2171 00004FCC C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2172                              <1> 
  2173                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2174                              <1> 
  2175                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2176                              <1>        ;decb    (r0)
  2177                              <1>        ;bge     1f / if less than 0
  2178                              <1>        ;clrb    (r0) / make it 0
  2179                              <1> ;1: / decrement time out counts return now if priority was not 0
  2180                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2181                              <1>        ;bge     2f / yes, check time outs
  2182                              <1>        ;tstb    (r0) / no, user timed out?
  2183                              <1>        ;bne     1f / no
  2184                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2185                              <1>        ;bne     1f / no, 1f
  2186                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2187                              <1>        ;sys     0 / sysrele
  2188                              <1>        ;rti
  2189                              <1> ;2: / priority is high so just decrement time out counts
  2190                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2191                              <1> ;2:
  2192                              <1>        ;tstb    (r0) / is the time out?
  2193                              <1>        ;beq     3f / yes, 3f (get next entry)
  2194                              <1>        ;decb    (r0) / no, decrement the time
  2195                              <1>        ;bne     3f / isit zero now?
  2196                              <1>        ;incb    (r0) / yes, increment the time
  2197                              <1> ;3:
  2198                              <1>        ;inc     r0 / next entry
  2199                              <1>        ;cmp     r0,$touts / end of toutt table?
  2200                              <1>        ;blo     2b / no, check this entry
  2201                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2202                              <1>        ;rti / return from interrupt
  2203                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2204                              <1>        ;mov     (sp)+,r0 / restore r0
  2205                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2206                              <1>        ;jsr     r0,setisp / save registers
  2207                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2208                              <1>                                ;  / the table
  2209                              <1> ;1:
  2210                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2211                              <1>        ;beq     2f / yes
  2212                              <1>        ;decb    toutt(r0) / no, decrement the time
  2213                              <1>        ;bne     2f / is the time 0, now
  2214                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2215                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2216                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2217                              <1> ;2:
  2218                              <1>        ;dec     r0 / set up r0 for next entry
  2219                              <1>        ;bge     1b / finished? , no, go back
  2220                              <1>        ;br      retisp / yes, restore registers and do a rti
  2221                              <1> 
  2222                              <1> ;retisp:
  2223                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2224                              <1>        ;mov     (sp)+,r3
  2225                              <1>        ;mov     (sp)+,r2
  2226                              <1>        ;mov     (sp)+,r1
  2227                              <1>        ;mov     (sp)+,r0
  2228                              <1>        ;rti     / return from interrupt
  2229                              <1> 
  2230                              <1> 
  2231                              <1> wakeup: ; / wakeup processes waiting for an event 
  2232                              <1> 	; / by linking them to the queue
  2233                              <1> 	;
  2234                              <1> 	; 26/02/2022
  2235                              <1> 	; 15/09/2015
  2236                              <1> 	; 29/06/2015
  2237                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2238                              <1> 	;
  2239                              <1> 	; 15/05/2013 - 02/06/2014
  2240                              <1> 	; Retro UNIX 8086 v1 modification !
  2241                              <1> 	; (Process/task switching routine by using
  2242                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2243                              <1> 	;
  2244                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2245                              <1> 	; sleeping in the specified wait channel by creating a link 
  2246                              <1> 	; to it from the last user process on the run queue.
  2247                              <1> 	; If there is no process to wake up, nothing happens.
  2248                              <1> 	;
  2249                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2250                              <1> 	; 'switching' status of the current process (owns current tty)
  2251                              <1> 	; (via alt + function keys) to a process which has highest
  2252                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2253                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2254                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2255                              <1> 	; tty for tty switching by keyboard.)	 
  2256                              <1> 	; 
  2257                              <1> 	; INPUT -> 
  2258                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2259                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2260                              <1> 	;
  2261                              <1> 	; ((modified registers: EAX, EBX))
  2262                              <1> 	;
  2263 00004FCD 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2264 00004FD0 81C3[E86C0000]      <1> 	add	ebx, wlist
  2265 00004FD6 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2266 00004FD8 20C0                <1> 	and	al, al
  2267 00004FDA 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2268                              <1> 	;
  2269 00004FDC 30E4                <1> 	xor	ah, ah
  2270 00004FDE 8825[8E700000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2271 00004FE4 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2272                              <1> 	; 15/09/2015
  2273 00004FE6 0FB6D8              <1> 	movzx	ebx, al
  2274                              <1> 	; 26/02/2022 (p.waitc is not used)
  2275                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2276 00004FE9 FEC4                <1> 	inc	ah
  2277 00004FEB 88A3[C76D0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2278                              <1> 	;
  2279 00004FF1 57                  <1> 	push	edi
  2280 00004FF2 52                  <1> 	push	edx
  2281 00004FF3 E851FFFFFF          <1> 	call	putlu
  2282 00004FF8 5A                  <1> 	pop	edx
  2283 00004FF9 5F                  <1> 	pop	edi
  2284                              <1> wa0:
  2285 00004FFA C3                  <1> 	retn
  2286                              <1> 
  2287                              <1> sleep: 
  2288                              <1> 	; 26/02/2022
  2289                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2290                              <1> 	; 15/09/2015
  2291                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2292                              <1> 	;
  2293                              <1> 	; 09/05/2013 - 20/03/2014
  2294                              <1> 	;
  2295                              <1> 	; Retro UNIX 8086 v1 modification !
  2296                              <1> 	; (Process/task switching and quit routine by using
  2297                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2298                              <1> 	;
  2299                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2300                              <1> 	; tty and tape output or input becomes available
  2301                              <1> 	; and process is put on waiting channel and swapped out,
  2302                              <1> 	; then -when the tty or tape is ready to write or read-
  2303                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2304                              <1> 	;
  2305                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2306                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2307                              <1> 	; status of the current process also INT 1Ch will count down
  2308                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2309                              <1> 	; to tty buffer of the current process and kernel will get
  2310                              <1> 	; user input by using tty buffer of the current process
  2311                              <1> 	; (instead of standard INT 16h interrupt).
  2312                              <1> 	; TTY output will be redirected to related video page of text mode
  2313                              <1> 	; (INT 10h will be called with different video page depending
  2314                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2315                              <1> 	; pseudo screens.)
  2316                              <1> 	;
  2317                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2318                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2319                              <1> 	; characters/data on serial port(s).
  2320                              <1> 	;
  2321                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2322                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2323                              <1> 	; 
  2324                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2325                              <1> 	;
  2326                              <1> 	;; 05/10/2013
  2327                              <1>         ;10/12/2013
  2328                              <1> 	;cmp   byte [u.uno], 1
  2329                              <1>         ;ja    short sleep0
  2330                              <1> 	;retn
  2331                              <1> 
  2332                              <1> 	; 20/03/2014
  2333                              <1> 	;mov	bx, [runq]
  2334                              <1> 	;cmp	bl, bh
  2335                              <1> 	;jne	short sleep0	
  2336                              <1> 	; 25/02/2014
  2337                              <1> 	;cmp word ptr [runq], 0
  2338                              <1> 	;ja short sleep0	
  2339                              <1> 	;retn
  2340                              <1> sleep0:
  2341                              <1> 	;
  2342 00004FFB E849000000          <1> 	call	isintr
  2343                              <1> 	;jnz	sysret
  2344                              <1> 		; / wait for event
  2345                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2346                              <1> 			      ; / or quit from user
  2347                              <1>                		; br 2f / something happened
  2348                              <1> 			      ; / yes, his interrupt so return
  2349                              <1>                      	      ;	/ to user
  2350                              <1> 	; 24/12/2021
  2351 00005000 7405                <1> 	jz	short sleep_2
  2352                              <1> sleep_3:
  2353 00005002 E9D8EAFFFF          <1> 	jmp	sysret
  2354                              <1> sleep_2:
  2355                              <1> 	; 30/06/2015
  2356 00005007 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2357 0000500A 81C3[E86C0000]      <1> 	add	ebx, wlist
  2358 00005010 8A03                <1> 	mov	al, [ebx]
  2359 00005012 20C0                <1> 	and	al, al
  2360 00005014 7407                <1> 	jz	short sleep1
  2361 00005016 53                  <1> 	push	ebx
  2362 00005017 E82DFFFFFF          <1> 	call	putlu
  2363 0000501C 5B                  <1> 	pop	ebx
  2364                              <1> sleep1:
  2365 0000501D A0[9B700000]        <1> 	mov	al, [u.uno]    
  2366 00005022 8803                <1>   	mov	[ebx], al 	; put the process number
  2367                              <1> 				; in the wait channel
  2368                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2369                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2370                              <1> 				     ; / on the stack
  2371                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2372                              <1> 				     ; / to put to sleep in there
  2373                              <1>         ; 15/09/2015
  2374 00005024 0FB6D8              <1> 	movzx	ebx, al
  2375 00005027 C683[C76D0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2376                              <1> 	; 26/02/2022 (p.waitc is not used)
  2377                              <1> 	;inc	ah
  2378                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2379                              <1> 	;
  2380 0000502E 66FF35[2F700000]    <1> 	push    word [cdev]
  2381                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2382 00005035 E842FEFFFF          <1> 	call	swap
  2383                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2384 0000503A 668F05[2F700000]    <1>         pop     word [cdev]
  2385                              <1> 		; mov (sp)+,cdev / restore device
  2386 00005041 E803000000          <1> 	call	isintr
  2387                              <1> 	; 22/09/2013
  2388                              <1> 	;jnz	sysret         
  2389                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2390                              <1>                		; br 2f / yes, return to new user
  2391                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2392                              <1> 				; / originally on the wait channel
  2393                              <1>        		; beq 1f / if 0 branch
  2394                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2395                              <1>        		; mov $300,*$ps / processor priority = 6
  2396                              <1> 		; jsr r0,putlu / create link to old process number
  2397                              <1>        		; clr *$ps / clear the status; process priority = 0
  2398                              <1> 	; 24/12/2021
  2399 00005046 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2400                              <1>      ;1:
  2401 00005048 C3                  <1> 	retn
  2402                              <1> 		; rts r0 / return
  2403                              <1>      ;2:
  2404                              <1>         ;;jmp	sysret
  2405                              <1> 		; jmp sysret / return to user
  2406                              <1> 
  2407                              <1> isintr:
  2408                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2409                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2410                              <1> 	;
  2411                              <1> 	; 09/05/2013 - 30/05/2014
  2412                              <1> 	;
  2413                              <1> 	; Retro UNIX 8086 v1 modification !
  2414                              <1> 	; (Process/task switching and quit routine by using
  2415                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2416                              <1> 	;
  2417                              <1> 	; Retro UNIX 8086 v1 modification:
  2418                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2419                              <1> 	;  and there is a 'quit' request by user;
  2420                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2421                              <1> 	;  "nothing to do". (20/10/2013)
  2422                              <1> 	;
  2423                              <1> 	; 20/10/2013
  2424 00005049 66833D[7C700000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2425 00005051 761F                <1> 	jna	short isintr2 ; retn
  2426                              <1> 	; 03/09/2013
  2427                              <1> 	; (nothing to do)
  2428                              <1> 	;retn
  2429                              <1> 	; 22/09/2013
  2430 00005053 66833D[90700000]00  <1> 	cmp	word [u.intr], 0
  2431 0000505B 7615                <1> 	jna	short isintr2 ; retn
  2432                              <1> 	; 30/05/2014
  2433                              <1> 	;push	ax
  2434                              <1> 	; 24/12/2021
  2435 0000505D 50                  <1> 	push	eax
  2436 0000505E 66A1[92700000]      <1> 	mov	ax, [u.quit]
  2437 00005064 6609C0              <1> 	or	ax, ax ; 0 ?
  2438 00005067 7408                <1> 	jz	short isintr1 ; zf = 1
  2439 00005069 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2440 0000506D 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2441                              <1> 	;xor	ax, ax ; zf = 1
  2442                              <1> 	; 24/12/2021
  2443 0000506F 31C0                <1> 	xor	eax, eax ; zf = 1
  2444                              <1> isintr1:
  2445                              <1> 	;pop	ax
  2446                              <1> 	; 24/12/2021
  2447 00005071 58                  <1> 	pop	eax
  2448                              <1> isintr2: ; 22/09/2013
  2449                              <1> 	; zf=1 -> nothing to do
  2450 00005072 C3                  <1> 	retn
  2451                              <1> 
  2452                              <1> 	; UNIX v1 original 'isintr' routine... 
  2453                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2454                              <1>        	;mov     r2,-(sp) / save r2
  2455                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2456                              <1>         ;                 / typewriter
  2457                              <1>        	;beq     1f / if 0, do nothing except skip return
  2458                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2459                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2460                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2461                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2462                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2463                              <1>         ;              / of interrupts
  2464                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2465                              <1>      ;1:
  2466                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2467                              <1>      ;4:
  2468                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2469                              <1>        	;mov     (sp)+,r1
  2470                              <1>        	;rts     r0
  2471                              <1>      ;3: / interrupt char = quit (fs)
  2472                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2473                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2474                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2475                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2476                              <1>      ;1: / find process control tty entry in tty block
  2477                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2478                              <1>        	;beq     1f / block found go to 1f
  2479                              <1>        	;add     $8,r1 / look at next tty block
  2480                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2481                              <1>        	;blo     1b / no
  2482                              <1>        	;br      4b / no process control tty found so go to 4b
  2483                              <1>      ;1:
  2484                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2485                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2486                              <1>         ;                  / identifier
  2487                              <1>        	;inc     0f / increment
  2488                              <1>      ;1:
  2489                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2490                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2491                              <1>         ;             / being typed out after you hit the interrupt
  2492                              <1>         ;             / key
  2493                              <1>        	;br      1b
  2106                                  %include 'u5.s'        ; 03/06/2015
  2107                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2108                              <1> ; Last Modification: 22/04/2022
  2109                              <1> ; ----------------------------------------------------------------------------
  2110                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2111                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2112                              <1> ;
  2113                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2114                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2115                              <1> ; <Bell Laboratories (17/3/1972)>
  2116                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2117                              <1> ;
  2118                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2119                              <1> ;
  2120                              <1> ; ****************************************************************************
  2121                              <1> 
  2122                              <1> mget:
  2123                              <1> 	; 22/04/2022
  2124                              <1> 	; 09/01/2022
  2125                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2126                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2127                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2128                              <1> 	;
  2129                              <1> 	; Get existing or (allocate) a new disk block for file
  2130                              <1> 	; 
  2131                              <1> 	; INPUTS ->
  2132                              <1> 	;    u.fofp (file offset pointer)
  2133                              <1> 	;    inode 
  2134                              <1> 	;    u.off (file offset)
  2135                              <1> 	; OUTPUTS ->
  2136                              <1> 	;    r1 (physical block number)
  2137                              <1> 	;    r2, r3, r5 (internal)
  2138                              <1> 	;
  2139                              <1> 	; ((AX = R1)) output
  2140                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2141                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2142                              <1> 
  2143                              <1> 		; mov *u.fofp,mq / file offset in mq
  2144                              <1> 		; clr ac / later to be high sig
  2145                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2146                              <1> 		; mov mq,r2
  2147                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2148                              <1> 		; bne 4f / branch for large file
  2149                              <1> mget_0:	
  2150                              <1> 	; 09/01/2022
  2151 00005073 29C0                <1> 	sub	eax, eax
  2152 00005075 29D2                <1> 	sub	edx, edx
  2153 00005077 29C9                <1> 	sub	ecx, ecx
  2154 00005079 29DB                <1> 	sub	ebx, ebx
  2155                              <1> 
  2156 0000507B 8B35[5C700000]      <1>         mov     esi, [u.fofp]
  2157                              <1>         ;movzx	ebx, byte [esi+1]
  2158                              <1> 	; 09/01/2022
  2159 00005081 46                  <1> 	inc	esi
  2160 00005082 8A1E                <1> 	mov	bl, [esi]
  2161                              <1> 
  2162                              <1> 	; BX = r2
  2163                              <1>         ; 24/12/2021
  2164 00005084 F605[496D0000]10    <1> 	test	byte [i.flgs+1], 10h
  2165                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2166                              <1> 				  ; is this a large or small file
  2167 0000508B 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2168                              <1> 
  2169 0000508D F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2170                              <1> 		; bit $!17,r2
  2171 00005090 7525                <1> 	jnz 	short mget_2
  2172                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2173 00005092 80E30E              <1>         and     bl, 0Eh  
  2174                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2175                              <1> 	; 09/01/2021
  2176 00005095 668B83[4E6D0000]    <1> 	mov	ax, [ebx+i.dskp]
  2177                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2178                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2179                              <1> 	; 24/12/2021
  2180 0000509C 09C0                <1> 	or	eax, eax
  2181                              <1> 	;or 	ax, ax
  2182 0000509E 7516                <1> 	jnz 	short mget_1 
  2183                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2184                              <1> 		       ; / for file
  2185 000050A0 E8A6000000          <1> 	call 	alloc
  2186                              <1> 		; jsr r0,alloc / allocate a new block
  2187                              <1>          ; eAX (r1) = Physical block number
  2188 000050A5 668983[4E6D0000]    <1> 	mov 	[ebx+i.dskp], ax
  2189                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2190 000050AC E835020000          <1> 	call 	setimod	
  2191                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2192 000050B1 E8C2FEFFFF          <1> 	call	clear
  2193                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2194                              <1> mget_1: ; 2:
  2195                              <1>         ; eAX (r1) = Physical block number
  2196 000050B6 C3                  <1> 	retn 
  2197                              <1> 		; rts r0
  2198                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2199 000050B7 E88F000000          <1> 	call 	alloc
  2200                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2201                              <1> 	                     ; / block number in r1
  2202                              <1>         ; eAX (r1) = Physical block number
  2203 000050BC E85E0D0000          <1> 	call 	wslot
  2204                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2205                              <1> 			     ; / first data word in buffer
  2206                              <1>         ; eAX (r1) = Physical block number
  2207                              <1> 	; 09/01/2022
  2208 000050C1 31C9                <1> 	xor	ecx, ecx
  2209 000050C3 B108                <1> 	mov	cl, 8
  2210                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2211                              <1> 		   ; into new indirect block area for the new
  2212                              <1> 		   ; large file		
  2213 000050C5 89DF                <1> 	mov 	edi, ebx ; r5
  2214 000050C7 BE[4E6D0000]        <1> 	mov 	esi, i.dskp 
  2215                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2216                              <1> 			   ; / block pointers
  2217                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2218                              <1> 			  ; / large file
  2219                              <1> 	; 22/04/2022
  2220 000050CC 50                  <1> 	push	eax ; * ; bugfix
  2221                              <1> 
  2222                              <1> 	;xor 	ax, ax ; mov ax, 0
  2223                              <1> 	; 24/12/2021
  2224 000050CD 31C0                <1> 	xor	eax, eax
  2225                              <1> mget_3: ;1:
  2226 000050CF 66A5                <1> 	movsw
  2227                              <1> 		; mov (r2),(r5)+
  2228 000050D1 668946FE            <1> 	mov 	[esi-2], ax
  2229                              <1> 		; clr (r2)+
  2230 000050D5 E2F8                <1> 	loop	mget_3 ; 1b
  2231                              <1> 		; dec r3
  2232                              <1> 		; bgt 1b
  2233                              <1> 
  2234 000050D7 B1F8                <1> 	mov 	cl, 256-8
  2235                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2236                              <1> mget_4:	; 1
  2237 000050D9 F366AB              <1> 	rep 	stosw
  2238                              <1> 		; clr (r5)+
  2239                              <1> 		; dec r3
  2240                              <1> 		; bgt 1b
  2241                              <1> 
  2242                              <1> 	; 22/04/2022
  2243                              <1> 	;pop	eax ; * ; bugfix
  2244                              <1> 
  2245                              <1> 	; 24/03/2013
  2246                              <1>         ; AX (r1) = Physical block number
  2247 000050DC E85A0D0000          <1> 	call	dskwr
  2248                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2249                              <1> 
  2250                              <1> 	; 22/04/2022
  2251 000050E1 58                  <1> 	pop	eax ; * ; bugfix
  2252                              <1> 
  2253                              <1>         ; eAX (r1) = Physical block number
  2254 000050E2 66A3[4E6D0000]      <1> 	mov 	[i.dskp], ax
  2255                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2256                              <1> 	; 09/01/2022
  2257 000050E8 800D[496D0000]10    <1> 	or	byte [i.flgs+1], 10h
  2258                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2259                              <1> 		; bis $10000,i.flgs / set large file bit 
  2260                              <1> 				  ; / in i.flgs word of i-node
  2261 000050EF E8F2010000          <1> 	call	setimod
  2262                              <1> 		; jsr r0,setimod / set i-node modified flag
  2263 000050F4 E97AFFFFFF          <1>         jmp     mget_0 
  2264                              <1> 		; br mget
  2265                              <1> 
  2266                              <1> mget_5:  ; 4 ; large file
  2267                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2268                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2269                              <1> 			    ; / in indirect block
  2270                              <1> 		; mov r2,-(sp) / save on stack (*)
  2271                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2272                              <1>        		          ; / indirect block
  2273                              <1> 		; bic $!16,r2
  2274 000050F9 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2275 000050FC 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2276                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2277                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2278                              <1> 	; There is always 1 indirect block for this file system
  2279                              <1> 	; 09/01/2022
  2280 000050FD 66A1[4E6D0000]      <1> 	mov	ax, [i.dskp]
  2281                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2282                              <1> 		; mov i.dskp(r2),r1
  2283                              <1> 	; 09/01/2022
  2284 00005103 09C0                <1> 	or	eax, eax
  2285                              <1> 	;or 	ax, ax ; R1
  2286 00005105 7515                <1> 	jnz 	short mget_6 ; 2f
  2287                              <1> 		; bne 2f / if no indirect block exists
  2288 00005107 E83F000000          <1> 	call 	alloc
  2289                              <1> 		; jsr r0,alloc / allocate a new block
  2290 0000510C 66A3[4E6D0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2291                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2292 00005112 E8CF010000          <1> 	call 	setimod
  2293                              <1> 		; jsr r0,setimod / set i-node modified byte
  2294                              <1> 	; eAX = new block number
  2295 00005117 E85CFEFFFF          <1> 	call 	clear
  2296                              <1> 		; jsr r0,clear / clear new block
  2297                              <1> mget_6: ;2
  2298                              <1> 	; 05/03/2013
  2299                              <1> 	; eAX = r1, physical block number (of indirect block)
  2300 0000511C E88C0C0000          <1> 	call 	dskrd ; read indirect block
  2301                              <1> 		; jsr r0,dskrd / read in indirect block
  2302 00005121 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2303                              <1> 		; mov (sp)+,r2 / get offset
  2304                              <1> 	; eAX = r1, physical block number (of indirect block)
  2305 00005122 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2306                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2307                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2308 00005123 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2309                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2310                              <1> 	                  ; / points to location of inter
  2311                              <1> 	; 09/01/2022
  2312 00005125 668B03              <1> 	mov	ax, [ebx]
  2313                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2314                              <1> 			      ; in file sought in R1 (AX)
  2315                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2316                              <1> 	               	    ; / sought in r1
  2317                              <1> 	; 09/01/2022
  2318 00005128 09C0                <1> 	or	eax, eax
  2319                              <1> 	;or 	ax, ax
  2320 0000512A 751D                <1>         jnz 	short mget_7 ; 2f
  2321                              <1> 		; bne 2f / if no block exists 
  2322 0000512C E81A000000          <1> 	call 	alloc
  2323                              <1> 		; jsr r0,alloc / allocate a new block
  2324 00005131 668903              <1> 	mov 	[ebx], ax ; R1
  2325                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2326                              <1> 	                    ; / indirect block
  2327 00005134 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2328                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2329 00005135 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2330 00005136 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2331 00005137 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2332                              <1> 		; mov (r2),-(sp) / save block number of new block
  2333                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2334 00005139 E8E10C0000          <1> 	call 	wslot
  2335                              <1> 		; jsr r0,wslot
  2336                              <1>         ; eAX (r1) = physical block number
  2337                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2338 0000513E E8F80C0000          <1> 	call 	dskwr
  2339                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2340                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2341                              <1> 			     ; / back out on disk
  2342 00005143 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2343                              <1> 		; mov (sp),r1 / restore block number of new block	
  2344                              <1> 	; eAX (r1) = physical block number of new block
  2345 00005144 E82FFEFFFF          <1> 	call 	clear
  2346                              <1> 		; jsr r0,clear / clear new block	
  2347                              <1> mget_7: ; 2
  2348 00005149 5A                  <1> 	pop 	edx ; **
  2349                              <1> 		; tst (sp)+ / bump stack pointer
  2350                              <1> 	; eAX (r1) = Block number of new block
  2351 0000514A C3                  <1> 	retn
  2352                              <1> 		; rts r0
  2353                              <1> 
  2354                              <1> alloc:
  2355                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2356                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2357                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2358                              <1> 	;
  2359                              <1> 	; get a free block and 
  2360                              <1> 	; set the corresponding bit in the free storage map
  2361                              <1> 	; 
  2362                              <1> 	; INPUTS ->
  2363                              <1> 	;    cdev (current device)
  2364                              <1> 	;    r2 
  2365                              <1> 	;    r3
  2366                              <1> 	; OUTPUTS ->
  2367                              <1> 	;    r1 (physical block number of block assigned)
  2368                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2369                              <1> 	;
  2370                              <1> 	; ((AX = R1)) output
  2371                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2372                              <1>         ;    ((Modified registers: DX, CX))  
  2373                              <1> 
  2374                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2375                              <1> 		;mov r3,-(sp)
  2376                              <1> 	;push 	ecx
  2377 0000514B 53                  <1> 	push 	ebx ; R2
  2378                              <1> 	;push 	edx ; R3
  2379 0000514C BB[0C7D0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2380                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2381 00005151 803D[2F700000]00    <1> 	cmp 	byte [cdev], 0
  2382                              <1> 		; tst cdev
  2383 00005158 7605                <1> 	jna	short alloc_1
  2384                              <1> 		; beq 1f / drum is device
  2385 0000515A BB[147F0000]        <1> 	mov	ebx, mount
  2386                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2387                              <1> 			      ; / free storage map
  2388                              <1> alloc_1: ; 1
  2389                              <1> 	; 09/01/2022
  2390                              <1> 	;sub	ecx, ecx
  2391                              <1> 	;sub	edx, edx
  2392                              <1> 	;sub	eax, eax
  2393                              <1> 
  2394 0000515F 668B0B              <1>         mov	cx, [ebx]
  2395                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2396                              <1> 			     ; / storage map
  2397                              <1> 	; 09/01/2022
  2398 00005162 C1E103              <1> 	shl	ecx, 3
  2399                              <1> 	;shl	cx, 3
  2400                              <1> 		; asl r1 / multiply r1 by eight gives 
  2401                              <1> 		; number of blocks in device
  2402                              <1> 		; asl r1
  2403                              <1> 		; asl r1
  2404                              <1> 	;;push	cx ;; 01/08/2013
  2405                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2406 00005165 31C0                <1> 	xor 	eax, eax ; 0
  2407                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2408                              <1> alloc_2: ; 1
  2409 00005167 43                  <1> 	inc 	ebx ; 18/8/2012
  2410 00005168 43                  <1> 	inc 	ebx ; 
  2411 00005169 668B13              <1> 	mov 	dx, [ebx]
  2412                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2413                              <1> 	; 09/01/2022
  2414 0000516C 09D2                <1> 	or	edx, edx
  2415                              <1> 	;or 	dx, dx
  2416 0000516E 750D                <1> 	jnz 	short alloc_3 ; 1f
  2417                              <1> 		; bne 1f / branch if any free blocks in this word	
  2418 00005170 6683C010            <1> 	add 	ax, 16
  2419                              <1> 		; add $16.,r1
  2420                              <1> 	; 09/01/2022
  2421 00005174 39C8                <1> 	cmp	eax, ecx
  2422                              <1> 	;cmp 	ax, cx    
  2423                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2424 00005176 72EF                <1> 	jb 	short alloc_2
  2425                              <1> 		; blo 1b
  2426                              <1> 	; 14/11/2015
  2427                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2428                              <1> 	;	because of a (DMA or another) r/w error, 
  2429                              <1> 	;	we will be here, at 'jmp panic' code address,
  2430                              <1> 	;	even if the (disk) file system space is not full !!!
  2431                              <1> 	;	(cx = 0)	
  2432                              <1> 	;
  2433 00005178 E901E2FFFF          <1> 	jmp     panic 
  2434                              <1> 		; jmp panic / found no free storage
  2435                              <1> alloc_3: ; 1
  2436                              <1> 	; 09/01/2022
  2437 0000517D D1EA                <1> 	shr	edx, 1
  2438                              <1> 	;shr	dx, 1
  2439                              <1> 		; asr r3 / find a free block
  2440 0000517F 7203                <1> 	jc	short alloc_4 ; 1f
  2441                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2442                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2443                              <1> 	; 09/01/2022
  2444 00005181 40                  <1> 	inc	eax
  2445                              <1> 	;inc	ax
  2446                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2447 00005182 EBF9                <1> 	jmp 	short alloc_3
  2448                              <1> 		; br 1b
  2449                              <1> alloc_4: ; 1:
  2450                              <1> 	;; pop cx ;; 01/08/2013
  2451                              <1> 		; tst (sp)+ / bump sp
  2452                              <1> 	; 02/04/2013 
  2453 00005184 E829000000          <1> 	call	free3
  2454                              <1> 		; jsr r0,3f / have found a free block
  2455                              <1> 	; 21/8/2012
  2456 00005189 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2457 0000518C 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2458                              <1> 		; bic r3,(r2) / set bit for this block 
  2459                              <1> 		            ; / i.e. assign block
  2460                              <1> 		; br 2f
  2461 0000518F EB09                <1> 	jmp 	short alloc_5
  2462                              <1> 
  2463                              <1> free:
  2464                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2465                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2466                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2467                              <1> 	;
  2468                              <1> 	; calculates byte address and bit position for given block number
  2469                              <1> 	; then sets the corresponding bit in the free storage map
  2470                              <1> 	; 
  2471                              <1> 	; INPUTS ->
  2472                              <1> 	;    r1 - block number for a block structured device
  2473                              <1> 	;    cdev - current device 
  2474                              <1> 	; OUTPUTS ->
  2475                              <1> 	;    free storage map is updated
  2476                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2477                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2478                              <1> 	;
  2479                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2480                              <1>         ;  ((Modified registers: DX, CX))  
  2481                              <1> 
  2482                              <1> 		;mov r2,-(sp) / save r2, r3
  2483                              <1> 		;mov r3,-(sp)
  2484                              <1> 	;push 	ecx
  2485 00005191 53                  <1> 	push 	ebx ; R2
  2486                              <1> 	;push 	edx ; R3 
  2487                              <1> 
  2488 00005192 E81B000000          <1>         call    free3
  2489                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2490                              <1> 				 ; / in free storage map for block
  2491 00005197 660913              <1> 	or 	[ebx], dx  
  2492                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2493                              <1> 			    ;  / indicates free block	
  2494                              <1> 	; 0 -> allocated, 1 -> free
  2495                              <1> 
  2496                              <1> alloc_5:
  2497                              <1> 	; 07/04/2013
  2498                              <1> free_1: ; 2:
  2499                              <1> 	;pop 	edx
  2500                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2501 0000519A 5B                  <1> 	pop	ebx
  2502                              <1> 		; mov (sp)+,r2
  2503                              <1> 	; pop	ecx
  2504 0000519B 803D[2F700000]00    <1> 	cmp 	byte [cdev], 0
  2505                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2506                              <1> 			 ; / cdev = 1, mountable device
  2507 000051A2 7707                <1> 	ja	short alloc_6 ; 1f
  2508                              <1> 		; bne 1f
  2509                              <1> 	;mov	byte [smod], 1
  2510 000051A4 FE05[3F700000]      <1> 	inc 	byte [smod]
  2511                              <1> 		; incb smod / set super block modified for drum
  2512                              <1> 	; eAX (r1) = block number
  2513 000051AA C3                  <1> 	retn
  2514                              <1> 		; rts r0
  2515                              <1> free_2:
  2516                              <1> alloc_6: ; 1:
  2517                              <1> 	;mov 	byte [mmod], 1
  2518 000051AB FE05[40700000]      <1> 	inc 	byte [mmod]
  2519                              <1> 		; incb	mmod 
  2520                              <1> 		  ; / set super block modified for mountable device
  2521                              <1> 	; eAX (r1) = block number
  2522 000051B1 C3                  <1> 	retn	
  2523                              <1> 		; rts r0
  2524                              <1> free3:
  2525                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2526                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2527                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2528                              <1> 	;
  2529                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2530                              <1> 	; 
  2531                              <1> alloc_free_3: ; 3
  2532                              <1> 	;mov 	dx, 1
  2533                              <1> 	; 09/01/2022
  2534 000051B2 31D2                <1> 	xor	edx, edx
  2535 000051B4 42                  <1> 	inc	edx
  2536                              <1> 	; edx = 1
  2537 000051B5 88C1                <1> 	mov 	cl, al
  2538                              <1> 		; mov r1,r2 / block number, k, = 1		
  2539 000051B7 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2540                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2541 000051BA 7402                <1> 	jz 	short free4
  2542                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2543                              <1> 			       ; / (k) mod 8
  2544                              <1> 	;shl 	dx, cl
  2545                              <1> 	; 09/01/2022
  2546 000051BC D3E2                <1> 	shl	edx, cl
  2547                              <1> free4:
  2548 000051BE 0FB7D8              <1> 	movzx 	ebx, ax
  2549                              <1> 		; mov r1,r2 / divide block number by 16
  2550                              <1> 	; 09/01/2022
  2551 000051C1 C1EB04              <1> 	shr	ebx, 4
  2552                              <1> 	;shr 	bx, 4
  2553                              <1> 		; asr r2
  2554                              <1> 		; asr r2
  2555                              <1> 		; asr r2
  2556                              <1> 		; asr r2
  2557                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2558                              <1> 		       ; / bit for block is in lower half of word
  2559                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2560                              <1> 		        ; / storage map
  2561                              <1> alloc_free_4: ; 1
  2562                              <1> 	; 09/01/2022
  2563 000051C4 D1E3                <1> 	shl	ebx, 1
  2564                              <1> 	;shl 	bx, 1
  2565                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2566 000051C6 81C3[0E7D0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2567                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2568                              <1> 	    		        ; / with block bit in it 	
  2569 000051CC 803D[2F700000]00    <1> 	cmp	byte [cdev], 0
  2570                              <1> 		; tst cdev
  2571 000051D3 7606                <1> 	jna	short alloc_free_5
  2572                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2573 000051D5 81C308020000        <1> 	add	ebx, mount - systm
  2574                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2575                              <1> 				    ; / mountable device with bit of block to be
  2576                              <1> 				    ; / freed
  2577                              <1> alloc_free_5: ; 1 
  2578 000051DB C3                  <1> 	retn
  2579                              <1> 		; rts r0 / return to 'free'
  2580                              <1> 	      ; 2
  2581                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2582                              <1> 	
  2583                              <1> iget:
  2584                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2585                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2586                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2587                              <1> 	;
  2588                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2589                              <1> 	;
  2590                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2591                              <1> 	; 
  2592                              <1> 	; INPUTS ->
  2593                              <1> 	;    ii - current i-number, rootdir
  2594                              <1> 	;    cdev - new i-node device
  2595                              <1> 	;    idev - current i-node device
  2596                              <1> 	;    imod - current i-node modified flag
  2597                              <1> 	;    mnti - cross device file i-number
  2598                              <1> 	;    r1 - i-numbe rof new i-node
  2599                              <1> 	;    mntd - mountable device number		
  2600                              <1> 	; 	 
  2601                              <1> 	; OUTPUTS ->
  2602                              <1> 	;    cdev, idev, imod, ii, r1
  2603                              <1> 	;
  2604                              <1> 	; ((AX = R1)) input/output
  2605                              <1> 	;
  2606                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2607                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2608                              <1> 
  2609 000051DC 8A15[2F700000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2610 000051E2 8A35[2E700000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2611                              <1> 	;
  2612 000051E8 663B05[2C700000]    <1> 	cmp 	ax, [ii]
  2613                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2614 000051EF 7504                <1> 	jne 	short iget_1
  2615                              <1> 		; bne 1f
  2616 000051F1 38F2                <1> 	cmp	dl, dh
  2617                              <1> 		; cmp idev,cdev
  2618                              <1> 			  ; / is device number of i-node = current device
  2619 000051F3 7472                <1>         je      short iget_5
  2620                              <1> 		; beq 2f
  2621                              <1> iget_1: ; 1:
  2622 000051F5 30DB                <1> 	xor	bl, bl
  2623 000051F7 381D[3E700000]      <1> 	cmp	[imod], bl ; 0	
  2624                              <1> 		; tstb imod / has i-node of current file
  2625                              <1> 			  ; / been modified i.e., imod set
  2626 000051FD 7629                <1> 	jna	short iget_2
  2627                              <1> 		; beq 1f
  2628 000051FF 881D[3E700000]      <1> 	mov	[imod], bl ; 0
  2629                              <1> 		;  clrb	imod / if it has, 
  2630                              <1> 			   ; / we must write the new i-node out on disk
  2631                              <1> 	; 24/12/2021
  2632 00005205 50                  <1> 	push	eax ; *
  2633                              <1> 	;push	ax
  2634                              <1> 		; mov r1,-(sp)
  2635                              <1> 	;mov	dl, [cdev]
  2636 00005206 52                  <1> 	push	edx ; **
  2637                              <1> 	;push	dx
  2638                              <1> 		; mov cdev,-(sp)
  2639 00005207 66A1[2C700000]      <1> 	mov	ax, [ii]
  2640                              <1> 		; mov ii,r1
  2641                              <1> 	;mov	dh, [idev]
  2642 0000520D 8835[2F700000]      <1> 	mov	[cdev], dh
  2643                              <1> 		; mov idev,cdev
  2644 00005213 FEC3                <1> 	inc	bl ; 1
  2645                              <1> 	; 31/07/2013
  2646 00005215 881D[D0700000]      <1> 	mov     [rw], bl ; 1 == write 
  2647                              <1> 	;;28/07/2013 rw -> u.rw
  2648                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2649 0000521B E848000000          <1> 	call	icalc
  2650                              <1> 		; jsr r0,icalc; 1
  2651                              <1> 	;pop	dx
  2652                              <1> 	; 24/12/2021
  2653 00005220 5A                  <1> 	pop	edx ; **
  2654 00005221 8815[2F700000]      <1> 	mov	[cdev], dl
  2655                              <1> 		; mov (sp)+,cdev
  2656                              <1> 	; 24/12/2021
  2657 00005227 58                  <1> 	pop	eax ; *
  2658                              <1> 	;pop	ax
  2659                              <1> 		; mov (sp)+,r1
  2660                              <1> iget_2: ; 1:
  2661 00005228 6621C0              <1> 	and	ax, ax
  2662                              <1> 		; tst r1 / is new i-number non zero
  2663 0000522B 7434                <1> 	jz	short iget_4 ; 2f
  2664                              <1> 		; beq 2f / branch if r1=0
  2665                              <1> 
  2666                              <1> 	;mov 	dl, [cdev]
  2667 0000522D 08D2                <1> 	or	dl, dl
  2668                              <1> 		; tst cdev / is the current device number non zero
  2669                              <1> 			 ; / (i.e., device =/ drum)
  2670 0000522F 7517                <1> 	jnz	short iget_3 ;  1f
  2671                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2672 00005231 663B05[34700000]    <1> 	cmp	ax, [mnti]			
  2673                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2674                              <1> 			    ; / file (root directory of mounted device)
  2675 00005238 750E                <1> 	jne	short iget_3 ; 1f
  2676                              <1> 		; bne 1f
  2677                              <1>         ;mov    bl, [mntd]
  2678 0000523A FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2679 0000523C 8815[2F700000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2680                              <1> 		; mov mntd,cdev / make mounted device the current device
  2681 00005242 66A1[3A700000]      <1> 	mov	ax, [rootdir]
  2682                              <1> 		; mov rootdir,r1
  2683                              <1> iget_3: ; 1:
  2684 00005248 66A3[2C700000]      <1> 	mov	[ii], ax
  2685                              <1> 		; mov r1,ii
  2686 0000524E 8815[2E700000]      <1> 	mov	[idev], dl ; cdev
  2687                              <1> 		; mov cdev,idev
  2688 00005254 30DB                <1> 	xor	bl, bl
  2689                              <1>         ; 31/07/2013
  2690 00005256 881D[D0700000]      <1> 	mov     [rw], bl ; 0 == read 
  2691                              <1> 	;;28/07/2013 rw -> u.rw       
  2692                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2693 0000525C E807000000          <1> 	call	icalc
  2694                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2695                              <1> iget_4: ; 2:
  2696 00005261 66A1[2C700000]      <1> 	mov	ax, [ii]
  2697                              <1> 		; mov ii,r1
  2698                              <1> iget_5:
  2699 00005267 C3                  <1> 	retn
  2700                              <1> 		; rts r0
  2701                              <1> 
  2702                              <1> icalc:
  2703                              <1> 	; 04/04/2022 (47->31)
  2704                              <1> 	;	(Inode Table/List Address modification)
  2705                              <1> 	; 09/01/2022
  2706                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2707                              <1> 	; 02/07/2015
  2708                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2709                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2710                              <1> 	;
  2711                              <1> 	; calculate physical block number from i-number then
  2712                              <1> 	; read or write that block
  2713                              <1> 	;
  2714                              <1> 	; 'icalc' is called from 'iget'
  2715                              <1> 	;
  2716                              <1> 	; for original unix v1:
  2717                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2718                              <1>        	; / (i+31.) mod 16. bytes from its start
  2719                              <1> 	;
  2720                              <1> 	; for retro unix 8086 v1:
  2721                              <1> 	;  i-node is located in block (i+47)/16 and
  2722                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2723                              <1> 	;
  2724                              <1> 	; INPUTS ->
  2725                              <1> 	;    r1 - i-number of i-node
  2726                              <1> 	; 	 
  2727                              <1> 	; OUTPUTS ->
  2728                              <1> 	;    inode r/w
  2729                              <1> 	;
  2730                              <1> 	; ((AX = R1)) input
  2731                              <1> 	;
  2732                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2733                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2734                              <1> 	;
  2735 00005268 0FB7D0              <1> 	movzx	edx, ax	
  2736                              <1> 	;add	dx, 47
  2737                              <1> 	; 04/04/2022
  2738 0000526B 6683C21F            <1> 	add	dx, 31
  2739 0000526F 89D0                <1> 	mov	eax, edx
  2740                              <1> 	;;add	ax, 47	; add 47 to inode number
  2741                              <1> 	;add	ax, 31
  2742                              <1> 		; add $31.,r1 / add 31. to i-number
  2743 00005271 50                  <1> 	push	eax
  2744                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2745                              <1> 	; 09/01/2022
  2746 00005272 C1E804              <1> 	shr	eax, 4
  2747                              <1> 	;shr 	ax, 4
  2748                              <1> 		; asr r1 / divide by 16.
  2749                              <1> 		; asr r1
  2750                              <1> 		; asr r1
  2751                              <1> 		; asr r1 / r1 contains block number of block
  2752                              <1> 		       ; / in which i-node exists
  2753 00005275 E8330B0000          <1> 	call	dskrd
  2754                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2755                              <1> 	; 31/07/2013
  2756 0000527A 803D[D0700000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2757                              <1> 	;; 28/07/2013 rw -> u.rw
  2758                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2759                              <1> 		; tst (r0)
  2760 00005281 7605                <1> 	jna	short icalc_1
  2761                              <1> 		; beq 1f / branch to wslot when argument
  2762                              <1> 		       ; / in icalc call = 1
  2763                              <1> 	; eAX = r1 = block number
  2764 00005283 E8970B0000          <1> 	call	wslot
  2765                              <1> 		; jsr r0,wslot / set up data buffer for write
  2766                              <1> 			     ; / (will be same buffer as dskrd got)
  2767                              <1> 	; eBX = r5 points to first word in data area for this block
  2768                              <1> icalc_1: ; 1:
  2769 00005288 5A                  <1> 	pop	edx 
  2770 00005289 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2771                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2772                              <1> 			      ; / gives (i+31.) mod 16
  2773 0000528C C1E205              <1> 	shl 	edx, 5
  2774                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2775 0000528F 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2776 00005291 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2777                              <1>           	; eSI (r5) points to first word in i-node i.	
  2778                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2779                              <1> 			     ; / 32.*(i+31.)mod16
  2780                              <1> 		; mov $5,lsh / for i-node i.
  2781                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2782 00005293 BF[486D0000]        <1> 	mov	edi, inode
  2783                              <1> 		; mov $inode,r1 / inode is address of first word 
  2784                              <1> 			      ; / of current i-node
  2785                              <1> 	; 09/01/2022
  2786 00005298 29C9                <1> 	sub	ecx, ecx
  2787 0000529A B108                <1> 	mov	cl, 8 
  2788                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2789                              <1> 		; mov $16.,r3
  2790                              <1>        ; 31/07/2013
  2791 0000529C 382D[D0700000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2792                              <1>        ;;28/07/2013 rw -> u.rw                 
  2793                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2794                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2795 000052A2 7609                <1> 	jna	short icalc_3
  2796                              <1> 		; beq 2f / r0 now contains proper return address 
  2797                              <1> 		       ; / for rts r0
  2798                              <1> icalc_2: ; 1:
  2799 000052A4 87F7                <1> 	xchg 	esi, edi
  2800                              <1> 	; overwrite old i-node (in buffer to be written)
  2801 000052A6 F3A5                <1> 	rep 	movsd
  2802                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2803                              <1> 		; dec r3
  2804                              <1> 		; bgt 1b
  2805                              <1> 	;call	dskwr
  2806                              <1> 		; jsr r0,dskwr / write inode out on device
  2807                              <1> 	;retn
  2808                              <1> 		; rts r0
  2809                              <1> 	; 24/12/2021
  2810 000052A8 E98E0B0000          <1> 	jmp	dskwr
  2811                              <1> 
  2812                              <1> icalc_3: ; 2:
  2813                              <1> 	; copy new i-node into inode area of (core) memory
  2814 000052AD F3A5                <1> 	rep 	movsd
  2815                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2816                              <1> 		                ; / "inode" area of core
  2817                              <1> 		; dec r3
  2818                              <1> 		; bgt 2b
  2819 000052AF C3                  <1> 	retn
  2820                              <1> 		; rts r0
  2821                              <1> 
  2822                              <1> access:
  2823                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2824                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2825                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2826                              <1> 	;
  2827                              <1> 	; check whether user is owner of file or user has read or write
  2828                              <1> 	; permission (based on i.flgs).
  2829                              <1> 	;
  2830                              <1> 	; INPUTS ->
  2831                              <1> 	;    r1 - i-number of file
  2832                              <1> 	;    u.uid
  2833                              <1> 	; arg0 -> (owner flag mask)	 		
  2834                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2835                              <1> 	; OUTPUTS ->
  2836                              <1> 	;    inode (or jump to error)
  2837                              <1> 	;
  2838                              <1> 	; ((AX = R1)) input/output
  2839                              <1> 	;
  2840                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2841                              <1> 	
  2842                              <1> 	;push	dx  ; save flags (DL)
  2843                              <1> 	; 24/12/2021
  2844 000052B0 52                  <1> 	push	edx ; save flags (DL)
  2845 000052B1 E826FFFFFF          <1> 	call	iget
  2846                              <1> 		; jsr r0,iget / read in i-node for current directory
  2847                              <1> 			    ; / (i-number passed in r1)
  2848 000052B6 8A0D[486D0000]      <1> 	mov	cl, [i.flgs]
  2849                              <1> 		; mov i.flgs,r2
  2850                              <1> 	; 24/12/2021
  2851 000052BC 5A                  <1> 	pop	edx ; restore flags (DL)
  2852                              <1> 	;pop	dx  ; restore flags (DL)
  2853 000052BD 8A35[98700000]      <1> 	mov	dh, [u.uid]
  2854 000052C3 3A35[4B6D0000]      <1> 	cmp	dh, [i.uid]
  2855                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2856 000052C9 7503                <1> 	jne	short access_1
  2857                              <1> 		; bne 1f / no, then branch
  2858 000052CB C0E902              <1> 	shr	cl, 2
  2859                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2860                              <1> 		        ; / read/write bits
  2861                              <1> 		; asrb r2
  2862                              <1> access_1: ; 1:
  2863 000052CE 20D1                <1> 	and	cl, dl
  2864                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2865                              <1> 			     ; / in access call
  2866 000052D0 7513                <1> 	jnz	short access_2
  2867                              <1> 		; bne 1f
  2868 000052D2 08F6                <1> 	or	dh, dh	; super user (root) ?
  2869                              <1> 		; tstb u.uid
  2870 000052D4 740F                <1> 	jz	short access_2 ; yes, super user
  2871                              <1> 	;jnz	error
  2872                              <1> 		; beq 1f
  2873                              <1> 		; jmp error
  2874 000052D6 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2874 000052DE 0000                <1>
  2875                              <1> 			; 'permission denied !' error
  2876 000052E0 E9DAE7FFFF          <1> 	jmp	error
  2877                              <1> 
  2878                              <1> access_2: ; 1:
  2879                              <1> 	; DL = flags
  2880 000052E5 C3                  <1> 	retn
  2881                              <1> 		; rts r0
  2882                              <1> 
  2883                              <1> setimod:
  2884                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2885                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2886                              <1> 	;
  2887                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2888                              <1> 	; the inode has been modified. Also puts the time of modification
  2889                              <1> 	; into the inode.
  2890                              <1> 	;
  2891                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2892                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2893                              <1> 	;
  2894                              <1> 	
  2895                              <1> 	;push 	edx
  2896 000052E6 50                  <1> 	push	eax
  2897                              <1> 
  2898 000052E7 C605[3E700000]01    <1> 	mov 	byte [imod], 1
  2899                              <1> 		; movb $1,imod / set current i-node modified bytes
  2900                              <1> 	; Erdogan Tan 14-7-2012
  2901 000052EE E81AE3FFFF          <1> 	call 	epoch
  2902                              <1> 		 ; mov s.time,i.mtim 
  2903                              <1> 			    ; / put present time into file modified time
  2904                              <1> 		 ; mov s.time+2,i.mtim+2
  2905                              <1> 
  2906 000052F3 A3[626D0000]        <1> 	mov 	[i.mtim], eax
  2907                              <1> 	
  2908                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2909                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2910 000052F8 833D[5E6D0000]00    <1> 	cmp	dword [i.ctim], 0
  2911 000052FF 7505                <1> 	jnz	short setimod_ok
  2912                              <1> 
  2913 00005301 A3[5E6D0000]        <1> 	mov 	[i.ctim], eax
  2914                              <1> 
  2915                              <1> setimod_ok: ; 31/07/2013
  2916 00005306 58                  <1> 	pop	eax
  2917                              <1> 	;pop	edx
  2918                              <1> 	
  2919 00005307 C3                  <1> 	retn
  2920                              <1> 		; rts r0
  2921                              <1> 
  2922                              <1> itrunc:
  2923                              <1> 	; 03/02/2022
  2924                              <1> 	; 09/01/2022
  2925                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2926                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2927                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2928                              <1> 	;
  2929                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2930                              <1> 	;  to zero length.
  2931                              <1> 	;
  2932                              <1> 	; INPUTS ->
  2933                              <1> 	;    r1 - i-number of i-node
  2934                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2935                              <1> 	;    i.flgs - large file flag		
  2936                              <1> 	;    i.size - size of file	
  2937                              <1> 	; 	 
  2938                              <1> 	; OUTPUTS ->
  2939                              <1> 	;    i.flgs - large file flag is cleared
  2940                              <1> 	;    i.size - set to 0	
  2941                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2942                              <1> 	;    setimod - set to indicate i-node has been modified
  2943                              <1> 	;    r1 - i-number of i-node  					
  2944                              <1> 	;
  2945                              <1> 	; ((AX = R1)) input/output
  2946                              <1> 	;
  2947                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2948                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2949                              <1> 
  2950 00005308 E8CFFEFFFF          <1> 	call	iget
  2951                              <1> 		; jsr r0,iget
  2952 0000530D BE[4E6D0000]        <1> 	mov	esi, i.dskp
  2953                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2954 00005312 31C0                <1> 	xor	eax, eax
  2955                              <1> itrunc_1: ; 1:
  2956 00005314 66AD                <1> 	lodsw
  2957                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2958                              <1> 	; 09/01/2022
  2959 00005316 09C0                <1> 	or	eax, eax
  2960                              <1> 	;or 	ax, ax
  2961 00005318 7433                <1> 	jz	short itrunc_5
  2962                              <1> 		; beq 5f
  2963 0000531A 56                  <1> 	push	esi
  2964                              <1> 		; mov r2,-(sp)
  2965                              <1> 	; 09/01/2022
  2966 0000531B F605[496D0000]10    <1> 	test	byte [i.flgs+1], 10h
  2967                              <1> 	;test	word [i.flgs], 1000h
  2968                              <1> 		; bit $10000,i.flgs / test large file bit?
  2969 00005322 7423                <1> 	jz	short itrunc_4
  2970                              <1> 		; beq 4f / if clear, branch
  2971 00005324 50                  <1> 	push	eax
  2972                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2973 00005325 E8830A0000          <1> 	call	dskrd
  2974                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2975                              <1> 			     ; / pointed to by r5
  2976                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2977                              <1> 	; 09/01/2022
  2978 0000532A 31C9                <1> 	xor	ecx, ecx
  2979 0000532C FEC5                <1> 	inc	ch ; mov ch, 1
  2980                              <1> 	; ecx = 256
  2981                              <1> 	;mov	ecx, 256
  2982                              <1> 		; mov $256.,r3 / move word count into r3
  2983 0000532E 89DE                <1> 	mov	esi, ebx
  2984                              <1> itrunc_2: ; 2:
  2985 00005330 66AD                <1> 	lodsw
  2986                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2987                              <1> 			     ; / physical block number
  2988                              <1> 	; 09/01/2022
  2989 00005332 21C0                <1> 	and	eax, eax
  2990                              <1> 	;and	ax, ax
  2991 00005334 7407                <1> 	jz	short itrunc_3
  2992                              <1> 		; beq 3f / branch if zero
  2993                              <1> 	; 24/12/2021
  2994 00005336 51                  <1> 	push	ecx
  2995                              <1> 	;push	cx
  2996                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2997                              <1> 	;push	esi
  2998                              <1> 		; mov r5,-(sp)
  2999 00005337 E855FEFFFF          <1> 	call	free
  3000                              <1> 		; jsr r0,free / free block in free storage map
  3001                              <1> 	;pop	esi
  3002                              <1> 		; mov(sp)+,r5
  3003                              <1> 	;pop	cx
  3004 0000533C 59                  <1> 	pop	ecx
  3005                              <1> 		; mov (sp)+,r3
  3006                              <1> itrunc_3: ; 3:
  3007 0000533D E2F1                <1> 	loop	itrunc_2
  3008                              <1> 		; dec r3 / decrement word count
  3009                              <1> 		; bgt 2b / branch if positive
  3010 0000533F 58                  <1> 	pop	eax
  3011                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3012                              <1> 			     ; / indirect block
  3013                              <1> 	; 01/08/2013
  3014                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3015                              <1> 	; 03/02/2022
  3016 00005340 8025[496D0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  3017                              <1> itrunc_4: ; 4:
  3018 00005347 E845FEFFFF          <1> 	call	free
  3019                              <1> 		; jsr r0,free / free indirect block
  3020 0000534C 5E                  <1> 	pop	esi
  3021                              <1> 		; mov (sp)+,r2
  3022                              <1> itrunc_5: ; 5:
  3023 0000534D 81FE[5E6D0000]      <1> 	cmp	esi, i.dskp+16
  3024                              <1> 		; cmp r2,$i.dskp+16.
  3025 00005353 72BF                <1> 	jb	short itrunc_1	
  3026                              <1> 		; bne 1b / branch until all i.dskp entries check
  3027                              <1> 	; 03/02/2022
  3028                              <1> 	;and	byte [i.flgs+1], 0EFh
  3029                              <1> 	; 01/08/2013
  3030                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3031                              <1> 		; bic $10000,i.flgs / clear large file bit
  3032 00005355 BF[4E6D0000]        <1> 	mov	edi, i.dskp
  3033                              <1> 	;mov	cx, 8
  3034                              <1> 	;xor 	ax, ax
  3035                              <1> 	; 09/01/2022
  3036 0000535A 29C9                <1> 	sub	ecx, ecx
  3037 0000535C B108                <1> 	mov	cl, 8
  3038 0000535E 29C0                <1> 	sub	eax, eax
  3039 00005360 66A3[4C6D0000]      <1> 	mov	[i.size], ax ; 0
  3040                              <1> 		; clr i.size / zero file size
  3041 00005366 F366AB              <1> 	rep	stosw
  3042                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3043                              <1> 			   ; / zero block pointers
  3044 00005369 E878FFFFFF          <1> 	call	setimod
  3045                              <1> 		; jsr r0,setimod / set i-node modified flag
  3046 0000536E 66A1[2C700000]      <1> 	mov	ax, [ii]
  3047                              <1> 		; mov ii,r1
  3048 00005374 C3                  <1> 	retn
  3049                              <1> 		; rts r0
  3050                              <1> 
  3051                              <1> imap:
  3052                              <1> 	; 11/02/2022
  3053                              <1> 	; 03/02/2022
  3054                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3055                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3056                              <1> 	;
  3057                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3058                              <1> 	; allocation bit for an i-node whose number in r1.
  3059                              <1> 	;
  3060                              <1> 	; INPUTS ->
  3061                              <1> 	;    r1 - contains an i-number
  3062                              <1> 	;    fsp - start of table containing open files
  3063                              <1> 	;
  3064                              <1> 	; OUTPUTS ->
  3065                              <1> 	;    r2 - byte address of byte with the allocation bit
  3066                              <1> 	;    mq - a mask to locate the bit position.	
  3067                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3068                              <1> 	;
  3069                              <1> 	; ((AX = R1)) input/output
  3070                              <1> 	; ((DL/DX = MQ)) output
  3071                              <1> 	; ((BX = R2)) output
  3072                              <1> 	;
  3073                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3074                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3075                              <1> 	;
  3076                              <1> 		; / get the byte that has the allocation bit for 
  3077                              <1> 		; / the i-number contained in r1
  3078                              <1> 	;mov	dx, 1
  3079 00005375 B201                <1> 	mov	dl, 1
  3080                              <1> 		; mov $1,mq / put 1 in the mq
  3081 00005377 0FB7D8              <1> 	movzx	ebx, ax
  3082                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3083                              <1>  		          ; / in the map we must find
  3084 0000537A 6683EB29            <1> 	sub	bx, 41
  3085                              <1> 		; sub $41.,r2 / r2 has i-41
  3086 0000537E 88D9                <1> 	mov	cl, bl
  3087                              <1> 		; mov r2,r3 / r3 has i-41
  3088 00005380 80E107              <1> 	and	cl, 7
  3089                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3090                              <1> 			   ; / the bit position
  3091 00005383 7402                <1> 	jz	short imap1
  3092                              <1> 	;shl	dx, cl
  3093 00005385 D2E2                <1> 	shl	dl, cl
  3094                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3095                              <1> imap1:			   ; / to the left to mask the correct bit
  3096                              <1> 	; 03/02/2022
  3097 00005387 C1EB03              <1> 	shr	ebx, 3
  3098                              <1> 	;shr	bx, 3
  3099                              <1> 		; asr r2
  3100                              <1> 		; asr r2
  3101                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3102                              <1> 		       ; / from the start of the map
  3103                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3104 0000538A BE[0C7D0000]        <1> 	mov	esi, systm
  3105                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3106                              <1> 				; / the super block for drum
  3107                              <1> 	;cmp	word [cdev], 0
  3108 0000538F 803D[2F700000]00    <1> 	cmp	byte [cdev], 0
  3109                              <1> 		; tst cdev / is the device the disk
  3110 00005396 7606                <1> 	jna	short imap2
  3111                              <1> 		; beq 1f / yes
  3112 00005398 81C608020000        <1> 	add	esi, mount - systm
  3113                              <1> 		; add $mount-systm,r2 / for mounted device,
  3114                              <1> 			; / r2 points to 1st word of its super block
  3115                              <1> imap2: ; 1:
  3116 0000539E 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3117                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3118 000053A1 6683C304            <1> 	add	bx, 4
  3119 000053A5 01F3                <1> 	add	ebx, esi
  3120                              <1>         	; add (sp)+,r2 / ?
  3121                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3122                              <1> 		      ;; (2 + free map size + 2)
  3123                              <1> 		; add $2,r2 / ?
  3124                              <1> 
  3125                              <1> 	; 11/02/2022
  3126 000053A7 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3127 000053AD 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3128                              <1> 			  ; if inode num overs inode count
  3129                              <1> 
  3130                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3131                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3132                              <1> 
  3133                              <1> 	; 11/02/2022
  3134                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3135                              <1> 	;	(number of requested inode > inode count)
  3136                              <1> 
  3137 000053AF C3                  <1> 	retn
  3138                              <1> 		; rts r0
  2107                                  %include 'u6.s'        ; 31/05/2015
  2108                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS6.INC
  2109                              <1> ; Last Modification: 13/06/2022
  2110                              <1> ; ----------------------------------------------------------------------------
  2111                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2112                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2113                              <1> ;
  2114                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2115                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2116                              <1> ; <Bell Laboratories (17/3/1972)>
  2117                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2118                              <1> ;
  2119                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2120                              <1> ;
  2121                              <1> ; ****************************************************************************
  2122                              <1> 
  2123                              <1> readi:
  2124                              <1> 	; 11/01/2022
  2125                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2126                              <1> 	; 20/05/2015
  2127                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2128                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2129                              <1> 	;
  2130                              <1> 	; Reads from an inode whose number in R1
  2131                              <1> 	; 
  2132                              <1> 	; INPUTS ->
  2133                              <1> 	;    r1 - inode number
  2134                              <1> 	;    u.count - byte count user desires
  2135                              <1> 	;    u.base - points to user buffer
  2136                              <1> 	;    u.fofp - points to word with current file offset
  2137                              <1> 	; OUTPUTS ->
  2138                              <1> 	;    u.count - cleared
  2139                              <1> 	;    u.nread - accumulates total bytes passed back
  2140                              <1> 	;
  2141                              <1> 	; ((AX = R1)) input/output
  2142                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2143                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2144                              <1> 
  2145 000053B0 31D2                <1> 	xor	edx, edx ; 0
  2146 000053B2 8915[74700000]      <1> 	mov 	[u.nread], edx ; 0
  2147                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2148 000053B8 668915[B1700000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2149 000053BF 3915[70700000]      <1> 	cmp 	[u.count], edx ; 0
  2150                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2151 000053C5 7701                <1> 	ja 	short readi_1 ; 1f
  2152                              <1> 		 ; bgt 1f / yes, branch
  2153 000053C7 C3                  <1> 	retn
  2154                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2155                              <1> readi_1: ; 1:
  2156                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2157 000053C8 6683F828            <1> 	cmp	ax, 40
  2158                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2159                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2160                              <1>         ;ja	dskr 
  2161                              <1> 		 ; ble 1f / yes, branch
  2162                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2163                              <1> 		 ;         / read file with i-node number (r1)
  2164                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2165                              <1> 	; 24/12/2021
  2166 000053CC 7605                <1> 	jna	short readi_3
  2167 000053CE E9CF000000          <1> 	jmp	dskr
  2168                              <1> readi_3:
  2169                              <1> 	; (20/05/2015)
  2170 000053D3 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2171                              <1> 	; 1:
  2172 000053D4 0FB6D8              <1> 	movzx	ebx, al
  2173                              <1> 	; 11/01/2022
  2174 000053D7 C1E302              <1> 	shl	ebx, 2
  2175                              <1> 	;shl	bx, 2
  2176                              <1> 		 ; asl r1 / multiply inode number by 2
  2177 000053DA 81C3[DE530000]      <1> 	add	ebx, readi_2 - 4
  2178 000053E0 FF23                <1> 	jmp	dword [ebx]	
  2179                              <1> 		 ; jmp *1f-2(r1)
  2180                              <1> readi_2: ; 1:
  2181 000053E2 [2E540000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2182                              <1> 		 ;rtty / tty; r1=2
  2183                              <1> 		 ;rppt / ppt; r1=4
  2184 000053E6 [7E540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2185                              <1> 		 ;rmem / mem; r1=6
  2186                              <1> 		 ;rrf0 / rf0
  2187                              <1> 		 ;rrk0 / rk0
  2188                              <1> 		 ;rtap / tap0
  2189                              <1> 		 ;rtap / tap1
  2190                              <1> 		 ;rtap / tap2
  2191                              <1> 		 ;rtap / tap3
  2192                              <1> 		 ;rtap / tap4
  2193                              <1> 		 ;rtap / tap5
  2194                              <1> 		 ;rtap / tap6
  2195                              <1> 		 ;rtap / tap7
  2196 000053EA [5E5C0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2197 000053EE [5E5C0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2198 000053F2 [5E5C0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2199 000053F6 [5E5C0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2200 000053FA [5E5C0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2201 000053FE [5E5C0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2202 00005402 [93540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2203 00005406 [7A540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2204                              <1> 		 ;rcvt / tty0
  2205 0000540A [7A540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2206                              <1> 		 ;rcvt / tty1
  2207 0000540E [7A540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2208                              <1> 		 ;rcvt / tty2
  2209 00005412 [7A540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2210                              <1> 		 ;rcvt / tty3
  2211 00005416 [7A540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2212                              <1> 		 ;rcvt / tty4
  2213 0000541A [7A540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2214                              <1> 		 ;rcvt / tty5
  2215 0000541E [7A540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2216                              <1> 		 ;rcvt / tty6
  2217 00005422 [7A540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2218                              <1> 		 ;rcvt / tty7
  2219 00005426 [7A540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2220                              <1> 		 ;rcrd / crd
  2221 0000542A [7A540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2222                              <1> 
  2223                              <1> rtty: ; / read from console tty
  2224                              <1> 	; 11/01/2022
  2225                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2226                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2227                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2228                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2229                              <1> 	;	     must be written immediate on video page (screen)
  2230                              <1> 	;	     when it is required.	
  2231                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2232                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2233                              <1> 	;
  2234                              <1> 	; Console tty buffer is PC keyboard buffer
  2235                              <1> 	; and keyboard-keystroke handling is different than original
  2236                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2237                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2238                              <1> 	;
  2239                              <1> 	; 06/12/2013
  2240 0000542E 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2241 00005435 8A83[A76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2242                              <1> rttys:
  2243                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2244                              <1> 	               ; / of the control and status block
  2245                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2246                              <1> 		       ; / tty buffer
  2247                              <1> 	; 28/07/2013
  2248 0000543B A2[A0700000]        <1> 	mov 	[u.ttyn], al
  2249                              <1> 	; 13/01/2014
  2250 00005440 FEC0                <1> 	inc	al
  2251 00005442 A2[7C700000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2252                              <1> rtty_nc: ; 01/02/2014
  2253                              <1> 	; 29/09/2013
  2254                              <1> 	;mov	ecx, 10
  2255                              <1> 	; 11/01/2022
  2256 00005447 29C9                <1> 	sub	ecx, ecx
  2257 00005449 B10A                <1> 	mov	cl, 10
  2258                              <1> rtty_1: 	; 01/02/2014
  2259                              <1> 	;push 	cx ; 29/09/2013
  2260                              <1> 	; 24/12/2021
  2261 0000544B 51                  <1> 	push	ecx
  2262                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2263 0000544C B001                <1> 	mov 	al, 1
  2264 0000544E E85B0C0000          <1> 	call 	getc
  2265                              <1> 	; 24/12/2021
  2266 00005453 59                  <1> 	pop	ecx
  2267                              <1> 	;pop 	cx ; 29/09/2013	
  2268 00005454 7516                <1> 	jnz	short rtty_2
  2269                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2270                              <1> 	               ; / of chars. Is this number non-zero?
  2271 00005456 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2272                              <1> 	; 05/10/2013
  2273 00005458 8A25[A0700000]      <1> 	mov	ah, [u.ttyn]
  2274                              <1> 	; 29/09/2013
  2275 0000545E E898FBFFFF          <1> 	call	sleep
  2276                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2277                              <1>                 ;           / (120 chars.)
  2278                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2279 00005463 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2280                              <1> 
  2281                              <1> rtty_idle:
  2282                              <1> 	; 29/07/2013
  2283 00005465 E804FBFFFF          <1> 	call 	idle
  2284 0000546A EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2285                              <1> 	;1:
  2286                              <1> 		; tst 2(r5) / is the number of characters zero
  2287                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2288                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2289                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2290                              <1> 		          ; / contains the next char.
  2291                              <1> 		; dec 2(r5) / decrement the character count
  2292                              <1> rtty_2:
  2293 0000546C 30C0                <1> 	xor 	al, al
  2294 0000546E E83B0C0000          <1> 	call 	getc
  2295 00005473 E892000000          <1> 	call	passc
  2296                              <1> 		; jsr r0,passc / move the character to core (user)
  2297                              <1> 	;; 17/10/2015 - 16/07/2015
  2298                              <1> 	; 19/06/2014
  2299                              <1> 	;;jnz	short rtty_nc
  2300 00005478 58                  <1> 	pop	eax  ; (20/05/2015)
  2301 00005479 C3                  <1> 	retn 
  2302                              <1> ;ret1:
  2303                              <1> 		; jmp ret / return to caller via 'ret'
  2304                              <1> 
  2305                              <1> rcvt:   ; < receive/read character from tty >
  2306                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2307                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2308                              <1> 	;
  2309                              <1> 	; Retro UNIX 8086 v1 modification !
  2310                              <1> 	; 
  2311                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2312                              <1> 	;		(exactly different than this one)
  2313                              <1> 	;	was in 'u9.s' file.
  2314                              <1> 	;
  2315 0000547A 2C0A                <1> 	sub 	al, 10
  2316                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2317                              <1> 	; 16/07/2013
  2318                              <1> 	; 21/05/2013
  2319 0000547C EBBD                <1>         jmp     short rttys
  2320                              <1>       
  2321                              <1> ;rppt: / read paper tape
  2322                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2323                              <1> ;			 / places
  2324                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2325                              <1> ;		       / also enables read bit in prs
  2326                              <1> ;	jsr	r0,passc / place character in users buffer area
  2327                              <1> ;	br	rppt
  2328                              <1> 
  2329                              <1> rmem: ; / transfer characters from memory to a user area of core
  2330                              <1> 	; 17/10/2015
  2331                              <1> 	; 11/06/2015
  2332                              <1> 	; 24/05/2015
  2333                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2334                              <1> 	;
  2335 0000547E 8B35[5C700000]      <1> 	mov     esi, [u.fofp]
  2336                              <1> rmem_1:
  2337 00005484 8B1E                <1>         mov     ebx, [esi]        
  2338                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2339                              <1> 		               ; / to be transferred to user
  2340 00005486 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2341                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2342                              <1> 			    ; / char in memory file
  2343 00005488 8A03                <1> 	mov	al, [ebx]
  2344                              <1> 		; movb (r1),r1 / get character from memory file, 
  2345                              <1> 		             ; / put it in r1
  2346 0000548A E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2347                              <1> 			     ;  / the next byte of the users core area
  2348                              <1> 		; br rmem / continue
  2349 0000548F 75F3                <1> 	jnz	short rmem_1
  2350                              <1> ret_:
  2351 00005491 58                  <1> 	pop	eax ; 09/06/2015
  2352 00005492 C3                  <1> 	retn
  2353                              <1> 
  2354                              <1> rlpr:
  2355                              <1> ;1:
  2356                              <1> ;rcrd:
  2357 00005493 C705[A1700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2357 0000549B 0000                <1>
  2358 0000549D E91DE6FFFF          <1> 	jmp	error
  2359                              <1> 		;jmp	error / see 'error' routine
  2360                              <1> 
  2361                              <1> dskr:
  2362                              <1> 	; 12/10/2015
  2363                              <1> 	; 21/08/2015
  2364                              <1> 	; 25/07/2015
  2365                              <1> 	; 10/07/2015
  2366                              <1> 	; 16/06/2015
  2367                              <1> 	; 31/05/2015
  2368                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2369                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2370                              <1> dskr_0:
  2371 000054A2 50                  <1> 	push	eax
  2372                              <1> 		; mov (sp),r1 / i-number in r1
  2373                              <1> 	; AX = i-number
  2374 000054A3 E834FDFFFF          <1> 	call	iget
  2375                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2376 000054A8 0FB715[4C6D0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2377                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2378 000054AF 8B1D[5C700000]      <1> 	mov	ebx, [u.fofp]
  2379 000054B5 2B13                <1> 	sub	edx, [ebx]
  2380                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2381                              <1>         ; 12/10/2015
  2382                              <1> 	; jna     short ret_ 
  2383                              <1> 		; blos ret
  2384 000054B7 7709                <1> 	ja	short dskr_1
  2385                              <1> 	;
  2386                              <1> dskr_retn: ; 12/10/2015
  2387 000054B9 58                  <1> 	pop	eax
  2388 000054BA C605[B3700000]00    <1> 	mov	byte [u.kcall], 0
  2389 000054C1 C3                  <1> 	retn	
  2390                              <1> dskr_1: 
  2391 000054C2 3B15[70700000]      <1> 	cmp     edx, [u.count] 
  2392                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2393                              <1> 			       ; / to carry out read
  2394 000054C8 7306                <1> 	jnb	short dskr_2
  2395                              <1> 		; bhis 1f
  2396 000054CA 8915[70700000]      <1> 	mov	[u.count], edx
  2397                              <1> 		; mov r2,u.count / no, just read to end of file
  2398                              <1> dskr_2: ; 1:
  2399                              <1> 	; AX = i-number
  2400 000054D0 E89EFBFFFF          <1> 	call	mget
  2401                              <1> 		; jsr r0,mget / returns physical block number of block 
  2402                              <1> 			    ; / in file where offset points
  2403                              <1> 	; eAX = physical block number
  2404 000054D5 E8D3080000          <1> 	call	dskrd
  2405                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2406                              <1> 			     ; / 1st word of data in buffer
  2407                              <1> 	; 09/06/2015
  2408 000054DA 803D[B3700000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2409 000054E1 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2410 000054E3 66833D[B1700000]00  <1> 	cmp	word [u.pcount], 0
  2411 000054EB 7705                <1> 	ja	short dskr_4
  2412                              <1> dskr_3:
  2413                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2414 000054ED E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2415                              <1> dskr_4:
  2416                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2417 000054F2 E831030000          <1> 	call	sioreg
  2418                              <1> 		; jsr r0,sioreg
  2419 000054F7 87F7                <1> 	xchg	esi, edi
  2420                              <1> 	; eDI = file (user data) offset
  2421                              <1> 	; eSI = sector (I/O) buffer offset
  2422                              <1> 	; eCX = byte count
  2423 000054F9 F3A4                <1> 	rep	movsb
  2424                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2425                              <1> 		                 ; / starting at u.base
  2426                              <1> 		; dec r3
  2427                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2428                              <1> 	; 25/07/2015
  2429                              <1> 	; eax = remain bytes in buffer
  2430                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2431 000054FB 09C0                <1> 	or	eax, eax
  2432 000054FD 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2433                              <1> 	; 03/08/2013
  2434                              <1> 	;pop	eax
  2435 000054FF 390D[70700000]      <1> 	cmp	[u.count], ecx ; 0
  2436                              <1> 		; tst u.count / all bytes read off disk
  2437                              <1> 		; bne dskr
  2438                              <1> 		; br ret
  2439                              <1>         ;ja	short dskr_0
  2440                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2441                              <1> 	;retn
  2442                              <1> 	; 12/10/2015
  2443 00005505 76B2                <1> 	jna	short dskr_retn
  2444 00005507 58                  <1> 	pop	eax  ; (i-node number)
  2445 00005508 EB98                <1> 	jmp	short dskr_0
  2446                              <1> 	
  2447                              <1> passc:
  2448                              <1> 	; 18/10/2015
  2449                              <1> 	; 10/07/2015
  2450                              <1> 	; 01/07/2015
  2451                              <1> 	; 08/06/2015
  2452                              <1> 	; 04/06/2015
  2453                              <1> 	; 20/05/2015
  2454                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2455                              <1> 	;
  2456                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2457                              <1> 	;		      to physical address
  2458 0000550A 66833D[B1700000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2459                              <1> 			     ; 1-4095 --> use previous physical base address
  2460                              <1> 			     ; in [u.pbase]
  2461 00005512 7705                <1> 	ja	short passc_3
  2462                              <1> 	; 08/06/2015 - 10/07/2015
  2463 00005514 E82C000000          <1> 	call	trans_addr_w
  2464                              <1> passc_3:
  2465                              <1> 	; 19/05/2015
  2466 00005519 66FF0D[B1700000]    <1> 	dec	word [u.pcount]
  2467                              <1> 	;
  2468 00005520 8B1D[AD700000]      <1> 	mov	ebx, [u.pbase]
  2469 00005526 8803                <1> 	mov	[ebx], al
  2470                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2471                              <1> 		               ; / users buffer
  2472 00005528 FF05[6C700000]      <1> 	inc	dword [u.base]
  2473                              <1> 		; inc u.base / increment the pointer to point to 
  2474                              <1> 			  ; / the next byte in users buffer
  2475 0000552E FF05[AD700000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2476 00005534 FF05[74700000]      <1> 	inc	dword [u.nread]
  2477                              <1> 		; inc u.nread / increment the number of bytes read
  2478 0000553A FF0D[70700000]      <1> 	dec	dword [u.count]
  2479                              <1> 		; dec u.count / decrement the number of bytes to be read
  2480                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2481 00005540 C3                  <1> 	retn
  2482                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2483                              <1> 		             ; / 'readi' by:
  2484                              <1> 		;/ (1) pop the return address off the stack into r0
  2485                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2486                              <1> 	;1:
  2487                              <1> 		; clr	*$ps / clear processor status
  2488                              <1> 		; rts r0 / return to address currently on top of stack
  2489                              <1> 
  2490                              <1> trans_addr_r:
  2491                              <1> 	; Translate virtual address to physical address 
  2492                              <1> 	; for reading from user's memory space
  2493                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2494                              <1> 	; 18/10/2015
  2495                              <1> 	; 10/07/2015
  2496                              <1> 	; 09/06/2015
  2497                              <1> 	; 08/06/2015 
  2498                              <1> 	; 04/06/2015
  2499                              <1> 	;
  2500                              <1> 	; 18/10/2015
  2501 00005541 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2502 00005543 EB04                <1> 	jmp 	short trans_addr_rw
  2503                              <1> 
  2504                              <1> 	;push	eax
  2505                              <1> 	;push	ebx
  2506                              <1> 	;mov	ebx, [u.base]
  2507                              <1> 	;call	get_physical_addr ; get physical address
  2508                              <1> 	;;jnc	short cpass_0
  2509                              <1> 	;jnc	short passc_1
  2510                              <1> 	;mov	[u.error], eax
  2511                              <1> 	;;pop	ebx
  2512                              <1> 	;;pop	eax
  2513                              <1> 	;jmp	error
  2514                              <1> ;cpass_0:
  2515                              <1> 	; 18/10/2015
  2516                              <1> 	; 20/05/2015
  2517                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2518                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2519                              <1> 	;pop	ebx
  2520                              <1> 	;pop	eax
  2521                              <1> 	;retn	; 08/06/2015
  2522                              <1> 
  2523                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2524                              <1> trans_addr_w:
  2525                              <1> 	; 31/12/2021
  2526                              <1> 	; Translate virtual address to physical address 
  2527                              <1> 	; for writing to user's memory space
  2528                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2529                              <1> 	; 18/10/2015
  2530                              <1> 	; 29/07/2015
  2531                              <1> 	; 10/07/2015
  2532                              <1> 	; 09/06/2015
  2533                              <1> 	; 08/06/2015
  2534                              <1> 	; 04/06/2015 (passc)
  2535                              <1> 	;
  2536                              <1> 	; 18/10/2015
  2537 00005545 29D2                <1> 	sub	edx, edx
  2538 00005547 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2539                              <1> trans_addr_rw:
  2540 00005549 50                  <1> 	push	eax
  2541 0000554A 53                  <1> 	push	ebx
  2542                              <1> 	; 18/10/2015
  2543 0000554B 52                  <1> 	push 	edx ; r/w sign (in DL)
  2544                              <1> 	;
  2545 0000554C 8B1D[6C700000]      <1> 	mov	ebx, [u.base]
  2546 00005552 E843DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2547 00005557 730A                <1> 	jnc	short passc_0
  2548 00005559 A3[A1700000]        <1> 	mov	[u.error], eax
  2549                              <1> 	;pop	edx
  2550                              <1> 	;pop 	ebx
  2551                              <1> 	;pop	eax
  2552 0000555E E95CE5FFFF          <1> 	jmp	error
  2553                              <1> passc_0:
  2554 00005563 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2555 00005566 5A                  <1> 	pop	edx ; 18/10/2015
  2556 00005567 7517                <1> 	jnz	short passc_1
  2557                              <1> 	; 18/10/2015
  2558 00005569 20D2                <1> 	and 	dl, dl
  2559 0000556B 7413                <1> 	jz	short passc_1
  2560                              <1> 	; 20/05/2015
  2561                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2562                              <1> 	; EBX = linear address
  2563 0000556D 51                  <1> 	push 	ecx
  2564 0000556E 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2565 0000556F E895DBFFFF          <1> 	call 	copy_page
  2566 00005574 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2567 00005575 59                  <1> 	pop	ecx
  2568 00005576 7217                <1> 	jc	short passc_2
  2569                              <1> 	; 24/12/2021
  2570                              <1> 	;push	eax ; physical address of the new/allocated page
  2571                              <1> 	;call	add_to_swap_queue
  2572                              <1> 	;pop	eax
  2573                              <1> 	; 18/10/2015
  2574 00005578 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2575                              <1> 	;mov 	ecx, PAGE_SIZE
  2576                              <1> 	;sub	ecx, ebx 
  2577 0000557E 01D8                <1> 	add	eax, ebx  
  2578                              <1> passc_1: 
  2579                              <1> 	; 18/10/2015
  2580                              <1> 	; 20/05/2015
  2581 00005580 A3[AD700000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2582 00005585 66890D[B1700000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2583 0000558C 5B                  <1> 	pop	ebx
  2584 0000558D 58                  <1> 	pop	eax
  2585 0000558E C3                  <1> 	retn	; 08/06/2015
  2586                              <1> passc_2:
  2587 0000558F C705[A1700000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2587 00005597 0000                <1>
  2588                              <1> 	;pop 	ebx
  2589                              <1> 	;pop	eax
  2590 00005599 E921E5FFFF          <1> 	jmp	error
  2591                              <1> 
  2592                              <1> writei:
  2593                              <1> 	; 13/06/2022
  2594                              <1> 	; 03/02/2022
  2595                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2596                              <1> 	; 20/05/2015
  2597                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2598                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2599                              <1> 	;
  2600                              <1> 	; Write data to file with inode number in R1
  2601                              <1> 	; 
  2602                              <1> 	; INPUTS ->
  2603                              <1> 	;    r1 - inode number
  2604                              <1> 	;    u.count - byte count to be written
  2605                              <1> 	;    u.base - points to user buffer
  2606                              <1> 	;    u.fofp - points to word with current file offset
  2607                              <1> 	; OUTPUTS ->
  2608                              <1> 	;    u.count - cleared
  2609                              <1> 	;    u.nread - accumulates total bytes passed back	
  2610                              <1> 	; ((AX = R1))
  2611                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2612                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2613                              <1> 
  2614 0000559E 31C9                <1> 	xor	ecx, ecx
  2615 000055A0 890D[74700000]      <1> 	mov 	[u.nread], ecx  ; 0
  2616                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2617                              <1> 		            ; / read or write calls
  2618 000055A6 66890D[B1700000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2619 000055AD 390D[70700000]      <1> 	cmp 	[u.count], ecx
  2620                              <1> 	;	; tst u.count / test the byte count specified by the user
  2621 000055B3 770B                <1> 	ja 	short writei_1 ; 1f
  2622                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2623                              <1> 
  2624                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2625 000055B5 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2626 000055B8 7505                <1> 	jne	short writei_0
  2627 000055BA E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2628                              <1> writei_0:
  2629 000055BF C3                  <1> 	retn
  2630                              <1> 	;	; rts r0 / no, return - no writing to do
  2631                              <1> writei_1: ;1:
  2632                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2633 000055C0 6683F828            <1> 	cmp 	ax, 40
  2634                              <1> 		; cmp r1,$40.
  2635                              <1> 		; / does the i-node number indicate a special file?
  2636                              <1> 	;ja	dskw 
  2637                              <1> 		; bgt dskw / no, branch to standard file output
  2638                              <1> 	; 24/12/2021
  2639 000055C4 7605                <1> 	jna	short writei_3
  2640 000055C6 E958010000          <1> 	jmp	dskw
  2641                              <1> writei_3:
  2642                              <1> 	; (20/05/2015)
  2643 000055CB 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2644 000055CC 0FB6D8              <1> 	movzx	ebx, al
  2645                              <1> 	; 03/02/2022
  2646 000055CF C1E302              <1> 	shl	ebx, 2
  2647                              <1> 	;shl	bx, 2
  2648                              <1> 		; asl r1 / yes, calculate the index into the special file
  2649 000055D2 81C3[D6550000]      <1> 	add	ebx, writei_2 - 4
  2650 000055D8 FF23                <1> 	jmp	dword [ebx]	
  2651                              <1> 		; jmp *1f-2(r1)
  2652                              <1> 		; / jump table and jump to the appropriate routine
  2653                              <1> writei_2: ;1:
  2654 000055DA [26560000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2655                              <1> 		 ;wtty / tty; r1=2
  2656                              <1> 		 ;wppt / ppt; r1=4
  2657 000055DE [79560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2658                              <1> 		 ;wmem / mem; r1=6
  2659                              <1> 		 ;wrf0 / rf0
  2660                              <1> 		 ;wrk0 / rk0
  2661                              <1> 		 ;wtap / tap0
  2662                              <1> 		 ;wtap / tap1
  2663                              <1> 		 ;wtap / tap2
  2664                              <1> 		 ;wtap / tap3
  2665                              <1> 		 ;wtap / tap4
  2666                              <1> 		 ;wtap / tap5
  2667                              <1> 		 ;wtap / tap6
  2668                              <1> 		 ;wtap / tap7
  2669 000055E2 [E75C0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2670 000055E6 [E75C0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2671 000055EA [E75C0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2672 000055EE [E75C0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2673 000055F2 [E75C0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2674 000055F6 [E75C0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2675 000055FA [A9560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2676 000055FE [73560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2677                              <1> 		 ;xmtt / tty0
  2678 00005602 [73560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2679                              <1> 		 ;xmtt / tty1
  2680 00005606 [73560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2681                              <1> 		 ;xmtt / tty2
  2682 0000560A [73560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2683                              <1> 		 ;xmtt / tty3
  2684 0000560E [73560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2685                              <1> 		 ;xmtt / tty4
  2686 00005612 [73560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2687                              <1> 		 ;xmtt / tty5
  2688 00005616 [73560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2689                              <1> 		 ;xmtt / tty6
  2690 0000561A [73560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2691                              <1> 		 ;xmtt / tty7
  2692 0000561E [73560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2693                              <1> 		; / wlpr / lpr
  2694 00005622 [73560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2695                              <1> 
  2696                              <1> wtty: ; write to console tty (write to screen)
  2697                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2698                              <1> 	; 18/11/2015
  2699                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2700                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2701                              <1> 	;
  2702                              <1> 	; Console tty output is on current video page
  2703                              <1> 	; Console tty character output procedure is changed here
  2704                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2705                              <1> 	;
  2706 00005626 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2707 0000562D 8AA3[A76D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2708 00005633 88E0                <1> 	mov	al, ah ; 07/07/2014
  2709                              <1> wttys:	
  2710                              <1> 	; 10/10/2013
  2711 00005635 8825[A0700000]      <1> 	mov 	[u.ttyn], ah
  2712                              <1> 	; 13/01/2014
  2713 0000563B FEC0                <1> 	inc	al
  2714 0000563D A2[7D700000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2715                              <1> wtty_nc: ; 15/05/2013
  2716                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2717 00005642 E881010000          <1> 	call	cpass
  2718                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2719                              <1> 		             ; / none go to return address in syswrite
  2720                              <1> 		; tst r1 / is character = null
  2721                              <1> 		; beq wtty / yes, get next character
  2722                              <1> 	; 10/10/2013
  2723 00005647 7428                <1> 	jz	short wret
  2724                              <1> 	;1 : 
  2725                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2726                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2727                              <1> 		;	          / than 20
  2728                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2729                              <1> 	; 27/06/2014
  2730                              <1> wtty_1:
  2731                              <1> 	; AH = tty number
  2732                              <1> 	; AL = ASCII code of the character
  2733                              <1> 	; 15/04/2014
  2734                              <1> 	;push	ax
  2735                              <1> 	; 24/12/2021
  2736 00005649 50                  <1> 	push	eax
  2737 0000564A E8CD0A0000          <1> 	call	putc ; 14/05/2013
  2738 0000564F 731D                <1> 	jnc	short wtty_2
  2739                              <1> 	; 18/11/2015
  2740 00005651 E818F9FFFF          <1> 	call	idle
  2741                              <1> 	;mov	ax, [esp]
  2742                              <1> 	; 24/12/2021
  2743 00005656 8B0424              <1> 	mov	eax, [esp]
  2744 00005659 E8BE0A0000          <1> 	call	putc
  2745 0000565E 730E                <1> 	jnc	short wtty_2 
  2746                              <1> 	; 02/06/2014
  2747 00005660 8A25[A0700000]      <1> 	mov	ah, [u.ttyn]
  2748 00005666 E890F9FFFF          <1> 	call	sleep
  2749                              <1> 	;pop	ax
  2750                              <1> 	; 24/12/2021
  2751 0000566B 58                  <1> 	pop	eax
  2752 0000566C EBDB                <1> 	jmp 	short wtty_1
  2753                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2754                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2755                              <1> 			      ; / console tty and
  2756                              <1> 		; br 	2f / place character in list; if none available
  2757                              <1> 		   	  ; / branch to put process to sleep
  2758                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2759                              <1> wtty_2:
  2760                              <1> 	; 15/04/2014
  2761                              <1> 	;pop	ax
  2762                              <1> 	; 24/12/2021
  2763 0000566E 58                  <1> 	pop	eax
  2764 0000566F EBD1                <1> 	jmp	short wtty_nc
  2765                              <1> 		; br wtty
  2766                              <1> wret:	; 10/10/2013 (20/05/2015)
  2767 00005671 58                  <1> 	pop	eax
  2768 00005672 C3                  <1> 	retn
  2769                              <1> 	;2:
  2770                              <1> 		;mov	r1,-(sp) / place character on stack
  2771                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2772                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2773                              <1> 		;br	1b / try again to place character in clist and output
  2774                              <1> 
  2775                              <1> xmtt:   ; < send/write character to tty >
  2776                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2777                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2778                              <1> 	;
  2779                              <1> 	; Retro UNIX 8086 v1 modification !
  2780                              <1> 	; 
  2781                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2782                              <1> 	;		(exactly different than this one)
  2783                              <1> 	;	was in 'u9.s' file.
  2784                              <1> 	;
  2785 00005673 2C0A                <1> 	sub 	al, 10
  2786                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2787                              <1> 	; 10/10/2013
  2788 00005675 88C4                <1> 	mov	ah, al
  2789                              <1> 	; 28/07/2013
  2790 00005677 EBBC                <1> 	jmp	short wttys
  2791                              <1> 
  2792                              <1> ;wppt:
  2793                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2794                              <1> ;		         / if none return to writei's calling routine
  2795                              <1> ;	jsr	r0,pptoc / output character on ppt
  2796                              <1> ;	br	wppt
  2797                              <1> 
  2798                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2799                              <1> 	; 17/10/2015
  2800                              <1> 	; 11/06/2015
  2801                              <1> 	; 24/05/2015
  2802                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2803                              <1> 	;
  2804 00005679 813D[10070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2804 0000567F [914F0000]          <1>
  2805 00005683 7415                <1>         je      short wmem_acc_err
  2806                              <1> 	;
  2807 00005685 8B35[5C700000]      <1>         mov     esi, [u.fofp] 
  2808                              <1> wmem_1:
  2809 0000568B E838010000          <1> 	call	cpass
  2810                              <1> 		; jsr r0,cpass / get next character from users area of
  2811                              <1> 			     ; / core and put it in r1
  2812                              <1>         	; mov r1,-(sp) / put character on the stack
  2813                              <1> 	; 20/09/2013
  2814 00005690 74DF                <1> 	jz	short wret ; wmem_2  
  2815 00005692 8B1E                <1>         mov     ebx, [esi]
  2816                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2817 00005694 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2818                              <1> 		; inc *u.fofp / increment file offset to point to next
  2819                              <1> 			    ; / available location in file
  2820 00005696 8803                <1> 	mov	[ebx], al	
  2821                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2822                              <1> 			        ; / assigned to it
  2823 00005698 EBF1                <1> 	jmp	short wmem_1
  2824                              <1> 		; br wmem / continue
  2825                              <1> 	;1:
  2826                              <1> 	;jmp	error / ?
  2827                              <1> ;wmem_2:	
  2828                              <1> ;	; 20/09/2013
  2829                              <1> ;	pop	ax
  2830                              <1> ;	retn
  2831                              <1> 
  2832                              <1> wmem_acc_err:
  2833 0000569A C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2833 000056A2 0000                <1>
  2834 000056A4 E916E4FFFF          <1> 	jmp	error
  2835                              <1> 
  2836                              <1> ;wlpr:
  2837                              <1> 	; 13/06/2022
  2838                              <1> 	;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2839                              <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> ; 13/06/2022 - Retro UNIX 386 v1.1 - PRINTER BIOS (Functions)
  2852                              <1> 
  2853                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2854                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2855                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2856                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2857                              <1> 
  2858                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2859                              <1> 
  2860                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2861                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2862                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2863                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2864                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2865                              <1> RESERVED	equ 00000110b	; NOPS
  2866                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2867                              <1> 
  2868                              <1> ;----------------------------------------------------------------
  2869                              <1> ;								:
  2870                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2871                              <1> ;								:
  2872                              <1> ;   CX has count of bytes to be printed 			:
  2873                              <1> ;   ES:DI point to source buffer contains characters		:
  2874                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2875                              <1> ;								:
  2876                              <1> ;----------------------------------------------------------------
  2877                              <1> 
  2878                              <1> wlpr:
  2879                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2880                              <1> PRN$WRIT:
  2881                              <1> 	; INPUT:
  2882                              <1> 	;	[u.count] = count of characters to be printed
  2883                              <1> 	;	[u.base] = buffer address in user's memory space
  2884                              <1> 	;
  2885                              <1> 	;	(if ECX = 0, printer status will be returned)
  2886                              <1> 	
  2887                              <1> 	;xor	ebx, ebx
  2888                              <1> PRN$LOOP:
  2889 000056A9 E81A010000          <1> 	call	cpass		  ; Get a character into AL
  2890 000056AE 7431                <1> 	jz	short pr_exit
  2891                              <1> 	;
  2892 000056B0 B302                <1> 	mov	bl, 2  ; retry count
  2893                              <1> PRN$OUT:
  2894                              <1> 	; al = character which will be printed
  2895 000056B2 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2896 000056B4 E850000000          <1> 	call	PRNOP
  2897 000056B9 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2898                              <1> PrRetry:
  2899                              <1> 	; al = character
  2900 000056BB FECB                <1> 	dec	bl
  2901 000056BD 75F3                <1> 	jnz	short PRN$OUT
  2902                              <1> pr_err_exit:
  2903 000056BF 0FB6C0              <1> 	movzx	eax, al
  2904 000056C2 A3[A1700000]        <1> 	mov	[u.error], eax
  2905 000056C7 A3[4C700000]        <1> 	mov	[u.r0], eax ; error code in AL
  2906 000056CC 8B2D[44700000]      <1> 	mov 	ebp, [u.sp]
  2907                              <1> 			; Kernel stack at the beginning of sys call
  2908 000056D2 8B15[74700000]      <1> 	mov	edx, [u.nread]
  2909 000056D8 4A                  <1> 	dec	edx ; last char failed
  2910 000056D9 895514              <1> 	mov	[ebp+20], edx ; count of printed chacters in edx
  2911 000056DC E9DEE3FFFF          <1> 	jmp	error
  2912                              <1> pr_exit:
  2913 000056E1 58                  <1> 	pop	eax ; inode number
  2914                              <1> 
  2915                              <1> 	;mov	eax, [u.nread]
  2916                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2917                              <1> 	;jmp	sysret
  2918 000056E2 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2919                              <1> 
  2920                              <1> ; 13/06/2022
  2921                              <1> 
  2922                              <1> ;----------------------------------------------------------------
  2923                              <1> ;								:
  2924                              <1> ;		PRINTER STATUS ROUTINE				:
  2925                              <1> ;								:
  2926                              <1> ;----------------------------------------------------------------
  2927                              <1> ;
  2928                              <1> 
  2929                              <1> lpr_stat:
  2930                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2931                              <1> PRN$STAT:
  2932 000056E3 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2933 000056E8 750E                <1> 	jnz	short prn_stat_retn
  2934                              <1> 				  ; if error jump to error routine
  2935                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2936 000056EA B01F                <1> 	mov	al, ERR_PRN_PAPER
  2937 000056EC F6C420              <1> 	test	ah, NOPAPERSTATUS
  2938 000056EF 7507                <1> 	jnz	short prn_stat_retn
  2939 000056F1 F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2940 000056F4 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2941 000056F6 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2942                              <1> prn_stat_retn:
  2943                              <1> 	; al = error code
  2944                              <1> 	; ah = status flags
  2945 000056F8 A3[4C700000]        <1> 	mov	[u.r0], eax
  2946                              <1> 	;movzx	eax, al
  2947                              <1> 	;mov 	[u.error], eax
  2948 000056FD 58                  <1> 	pop	eax ; discard return address to syswrite
  2949 000056FE E9DCE3FFFF          <1> 	jmp	sysret
  2950                              <1> prn_stat_ok:
  2951 00005703 30C0                <1> 	xor	al, al ; 0
  2952 00005705 EBF1                <1> 	jmp	short prn_stat_retn
  2953                              <1> 
  2954                              <1> ;
  2955                              <1> ;   PRNSTAT	get printer status
  2956                              <1> ;   PRNOP	print a character
  2957                              <1> ;
  2958                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2959                              <1> ; printer routines.  The routines share code which calls on the bios and
  2960                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2961                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2962                              <1> ;
  2963                              <1> ;   INPUT	if PRNOP then character in AL
  2964                              <1> ;
  2965                              <1> ;   OUTPUT	- AL holds error code
  2966                              <1> ;		- AH status byte from printer
  2967                              <1> ;		- flag NZ if error
  2968                              <1> 
  2969                              <1> PRNSTAT:
  2970 00005707 B402                <1> 	mov	ah, 2		  ; set command for get status 
  2971                              <1> 
  2972                              <1> PRNOP:
  2973                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2974                              <1> 	;
  2975                              <1> 	; Print character (on paper)
  2976                              <1> 
  2977                              <1> 	; INPUT:
  2978                              <1> 	;	al = character to be printed
  2979                              <1> 	; OUTPUT:
  2980                              <1> 	;	zf = 1 -> ok
  2981                              <1> 	;	zf = 0 -> error code in AL
  2982                              <1> 
  2983 00005709 E8470C0000          <1> 	call	int17h	 ; call lpt bios
  2984                              <1> 	
  2985 0000570E F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  2986 00005711 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  2987                              <1> 
  2988                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  2989                              <1> 	; THE CONVERSE IS NOT TRUE.
  2990                              <1> 
  2991                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  2992 00005713 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2993 00005715 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  2994 00005718 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  2995                              <1> 	;mov	al, ERR_PRN_IO
  2996 0000571A FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  2997                              <1> PRNOP1: 
  2998                              <1> 
  2999                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  3000                              <1> 
  3001 0000571C C3                  <1> 	retn			  ; RETURN WITH ERROR
  3002                              <1>  
  3003                              <1> ; THE BITS SAID NO ERROR.
  3004                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  3005                              <1> 
  3006                              <1> prnop_chk_nrdy:
  3007                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  3008 0000571D B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  3009                              <1> 	
  3010 0000571F F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  3011                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  3012                              <1> PRNOP2: 
  3013 00005722 C3                  <1> 	retn
  3014                              <1> 
  3015                              <1> 
  3016                              <1> dskw: ; / write routine for non-special files
  3017                              <1> 	;
  3018                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3019                              <1> 	; 25/07/2015
  3020                              <1> 	; 16/06/2015
  3021                              <1> 	; 09/06/2015
  3022                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  3023                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  3024                              <1> 	;
  3025                              <1> 	; 01/08/2013 (mkdir_w check)
  3026                              <1> 
  3027                              <1> 	;push	ax ; 26/04/2013
  3028                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  3029                              <1> 	; 24/12/2021
  3030 00005723 50                  <1> 	push	eax
  3031                              <1> 	; AX = inode number
  3032 00005724 E8B3FAFFFF          <1> 	call	iget
  3033                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  3034                              <1> 		            ; / read i-node 'r1' into i-node area of core
  3035 00005729 8B1D[5C700000]      <1>         mov     ebx, [u.fofp] 
  3036 0000572F 8B13                <1> 	mov 	edx, [ebx]
  3037                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  3038                              <1> 			       ; / in the fsp entry for this file] in r2
  3039 00005731 0315[70700000]      <1> 	add 	edx, [u.count]	
  3040                              <1> 		; add u.count,r2 / no. of bytes to be written
  3041                              <1> 			       ; / + file offset is put in r2
  3042                              <1> 	; 16/06/2015        
  3043 00005737 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  3044 0000573D 760F                <1> 	jna	short dskw_0
  3045 0000573F C705[A1700000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  3045 00005747 0000                <1>
  3046 00005749 E971E3FFFF          <1> 	jmp	error
  3047                              <1> dskw_0:	
  3048 0000574E 663B15[4C6D0000]    <1> 	cmp     dx, [i.size]
  3049                              <1> 		; cmp r2,i.size / is this greater than the present size of
  3050                              <1> 		              ; / the file?
  3051 00005755 760C                <1> 	jna	short dskw_1
  3052                              <1> 		; blos 1f / no, branch
  3053 00005757 668915[4C6D0000]    <1>         mov     [i.size], dx
  3054                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3055                              <1> 			      ; / file offset + no. of data bytes
  3056 0000575E E883FBFFFF          <1> 	call	setimod
  3057                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3058                              <1> 		          ; / modified), stuff time of modification into
  3059                              <1> 	          	  ; / core image of i-node
  3060                              <1> dskw_1: ; 1:	
  3061 00005763 E80BF9FFFF          <1> 	call	mget
  3062                              <1> 	; eAX = Block number
  3063                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3064                              <1> 			    ; /	the next data byte
  3065                              <1> 	; eax = block number
  3066 00005768 8B1D[5C700000]      <1> 	mov     ebx, [u.fofp]
  3067 0000576E 8B13                <1> 	mov	edx, [ebx]
  3068 00005770 81E2FF010000        <1> 	and	edx, 1FFh  
  3069                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3070 00005776 750C                <1> 	jnz	short dskw_2
  3071                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3072                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3073 00005778 813D[70700000]0002- <1> 	cmp	dword [u.count], 512
  3073 00005780 0000                <1>
  3074                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3075                              <1> 				  ; / an entire block? (i.e., no. of
  3076 00005782 7305                <1> 	jnb	short dskw_3
  3077                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3078                              <1> 			; / Yes, branch. Don't have to read block
  3079                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3080                              <1>    		; / overwritten).
  3081 00005784 E824060000          <1> 	call	dskrd
  3082                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3083                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3084                              <1> dskw_3: ; 3:
  3085                              <1> 	; eAX (r1) = block/sector number
  3086 00005789 E891060000          <1> 	call	wslot
  3087                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3088                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3089 0000578E 803D[B3700000]00    <1> 	cmp	byte [u.kcall], 0
  3090 00005795 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3091                              <1> 	;
  3092 00005797 66833D[B1700000]00  <1> 	cmp	word [u.pcount], 0
  3093 0000579F 7705                <1> 	ja	short dskw_5
  3094                              <1> dskw_4:
  3095                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3096 000057A1 E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3097                              <1> dskw_5:
  3098                              <1> 	; eBX (r5) = system (I/O) buffer address
  3099 000057A6 E87D000000          <1> 	call	sioreg
  3100                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3101                              <1> 			     ; / r1 = address of data, r2 points to location
  3102                              <1> 			     ; / in buffer in which to start writing data
  3103                              <1> 	; eSI = file (user data) offset
  3104                              <1> 	; eDI = sector (I/O) buffer offset
  3105                              <1> 	; eCX = byte count
  3106                              <1> 	;
  3107 000057AB F3A4                <1>   	rep	movsb
  3108                              <1> 		; movb (r1 )+,(r2)+ 
  3109                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3110                              <1> 		; dec r3 / decrement no. of bytes to be written
  3111                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3112                              <1> 	; 25/07/2015
  3113                              <1> 	; eax = remain bytes in buffer
  3114                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3115 000057AD 09C0                <1> 	or	eax, eax
  3116 000057AF 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3117                              <1> dskw_6:
  3118 000057B1 E885060000          <1> 	call	dskwr
  3119                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3120 000057B6 833D[70700000]00    <1>         cmp     dword [u.count], 0
  3121                              <1> 		; tst u.count / any more data to write?
  3122 000057BD 77A4                <1> 	ja	short dskw_1
  3123                              <1> 		; bne 1b / yes, branch
  3124                              <1> 	; 03/08/2013
  3125 000057BF C605[B3700000]00    <1> 	mov	byte [u.kcall], 0
  3126                              <1> 	; 20/09/2013 (;;)
  3127                              <1> 	;pop	ax
  3128                              <1> 	; 24/12/2021
  3129 000057C6 58                  <1> 	pop	eax
  3130 000057C7 C3                  <1> 	retn
  3131                              <1> 	;;jmp 	short dskw_ret 
  3132                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3133                              <1> 
  3134                              <1> cpass: ; / get next character from user area of core and put it in r1
  3135                              <1> 	; 18/10/2015
  3136                              <1> 	; 10/10/2015
  3137                              <1> 	; 10/07/2015
  3138                              <1> 	; 02/07/2015
  3139                              <1> 	; 01/07/2015
  3140                              <1> 	; 24/06/2015
  3141                              <1> 	; 08/06/2015
  3142                              <1> 	; 04/06/2015
  3143                              <1> 	; 20/05/2015
  3144                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3145                              <1> 	;
  3146                              <1> 	; INPUTS -> 
  3147                              <1> 	;     [u.base] = virtual address in user area
  3148                              <1> 	;     [u.count] = byte count (max.)
  3149                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3150                              <1> 	; OUTPUTS -> 
  3151                              <1> 	;     AL = the character which is pointed by [u.base]
  3152                              <1> 	;     zf = 1 -> transfer count has been completed	
  3153                              <1>         ;
  3154                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3155                              <1> 	;
  3156                              <1> 	;
  3157 000057C8 833D[70700000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3158                              <1> 		; tst u.count / have all the characters been transferred
  3159                              <1> 			    ; / (i.e., u.count, # of chars. left
  3160 000057CF 763F                <1> 	jna	short cpass_3
  3161                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3162 000057D1 FF0D[70700000]      <1> 	dec	dword [u.count]
  3163                              <1> 		; dec u.count / no, decrement u.count
  3164                              <1>         ; 19/05/2015 
  3165                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3166                              <1> 	;		      to physical address
  3167 000057D7 66833D[B1700000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3168                              <1> 			     ; 1-4095 --> use previous physical base address
  3169                              <1> 			     ; in [u.pbase]
  3170 000057DF 770E                <1> 	ja	short cpass_1
  3171                              <1> 	; 02/07/2015
  3172 000057E1 833D[A9700000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3173 000057E8 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3174                              <1> 	; 08/06/2015 - 10/07/2015
  3175 000057EA E852FDFFFF          <1> 	call	trans_addr_r
  3176                              <1> cpass_1:
  3177                              <1> 	; 02/07/2015
  3178                              <1> 	; 24/06/2015
  3179 000057EF 66FF0D[B1700000]    <1> 	dec	word [u.pcount]
  3180                              <1> cpass_2: 
  3181                              <1> 	; 10/10/2015
  3182                              <1> 	; 02/07/2015
  3183 000057F6 8B15[AD700000]      <1> 	mov	edx, [u.pbase]
  3184 000057FC 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3185                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3186                              <1> 				; / by u.base and put it in r1
  3187 000057FE FF05[74700000]      <1> 	inc	dword [u.nread]
  3188                              <1> 		; inc u.nread / increment no. of bytes transferred
  3189 00005804 FF05[6C700000]      <1> 	inc	dword [u.base]
  3190                              <1> 		; inc u.base / increment the buffer address to point to the
  3191                              <1> 			   ; / next byte
  3192 0000580A FF05[AD700000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3193                              <1> cpass_3:
  3194 00005810 C3                  <1> 	retn
  3195                              <1> 		; rts	r0 / next byte
  3196                              <1> 	; 1: 
  3197                              <1> 		; mov (sp)+,r0 
  3198                              <1> 		         ; / put return address of calling routine into r0
  3199                              <1> 		; mov (sp)+,r1 / i-number in r1
  3200                              <1> 		; rts r0 / non-local return
  3201                              <1> cpass_k:
  3202                              <1> 	; 02/07/2015
  3203                              <1> 	; The caller is os kernel 
  3204                              <1> 	; (get sysexec arguments from kernel's memory space)
  3205                              <1> 	;
  3206 00005811 8B1D[6C700000]      <1> 	mov	ebx, [u.base]
  3207 00005817 66C705[B1700000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3207 0000581F 10                  <1>
  3208 00005820 891D[AD700000]      <1> 	mov	[u.pbase], ebx
  3209 00005826 EBCE                <1> 	jmp	short cpass_2
  3210                              <1> 	
  3211                              <1> sioreg: 
  3212                              <1> 	; 25/07/2015
  3213                              <1> 	; 18/07/2015
  3214                              <1> 	; 02/07/2015
  3215                              <1> 	; 17/06/2015
  3216                              <1> 	; 09/06/2015
  3217                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3218                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3219                              <1> 	;
  3220                              <1> 	; INPUTS -> 
  3221                              <1> 	;     eBX = system buffer (data) address (r5)
  3222                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3223                              <1> 	;     [u.base] = virtual address of the user buffer
  3224                              <1> 	;     [u.pbase] = physical address of the user buffer
  3225                              <1> 	;     [u.count] = byte count
  3226                              <1> 	;     [u.pcount] = byte count within page frame 			
  3227                              <1> 	; OUTPUTS -> 
  3228                              <1> 	;     eSI = user data offset (r1)
  3229                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3230                              <1> 	;     eCX = byte count (r3)
  3231                              <1> 	;     EAX = remain bytes after byte count within page frame
  3232                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3233                              <1>         ;
  3234                              <1> 	; ((Modified registers:  EDX))
  3235                              <1>  
  3236 00005828 8B35[5C700000]      <1>         mov     esi, [u.fofp]
  3237 0000582E 8B3E                <1>         mov     edi, [esi]
  3238                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3239 00005830 89F9                <1> 	mov	ecx, edi
  3240                              <1> 		; mov r2,r3 / and also to r3
  3241 00005832 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3242                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3243 00005838 81E7FF010000        <1> 	and	edi, 1FFh
  3244                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3245 0000583E 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3246                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3247                              <1> 			  ; / where data is to be placed
  3248                              <1>                 ; mov u.base,r1 / address of data is in r1
  3249 00005840 F7D9                <1> 	neg	ecx
  3250                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3251                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3252 00005842 3B0D[70700000]      <1> 	cmp	ecx, [u.count]
  3253                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3254                              <1> 			       ; / to be written to the file
  3255 00005848 7606                <1> 	jna	short sioreg_0
  3256                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3257                              <1> 			 ; / in the file block as the number to be written
  3258 0000584A 8B0D[70700000]      <1> 	mov	ecx, [u.count]
  3259                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3260                              <1> 			       ; / bytes as the number to be written
  3261                              <1> sioreg_0:
  3262                              <1> 	; 17/06/2015
  3263 00005850 803D[B3700000]00    <1> 	cmp	byte [u.kcall], 0 
  3264 00005857 7613                <1> 	jna	short sioreg_1
  3265                              <1> 	; 25/07/2015
  3266                              <1> 	; the caller is 'mkdir' or 'namei'
  3267 00005859 A1[6C700000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3268 0000585E A3[AD700000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3269 00005863 66890D[B1700000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3270 0000586A EB0B                <1> 	jmp	short sioreg_2
  3271                              <1> sioreg_1:
  3272                              <1> 	; 25/07/2015
  3273                              <1> 	; 18/07/2015
  3274                              <1> 	; 09/06/2015 
  3275 0000586C 0FB715[B1700000]    <1> 	movzx	edx, word [u.pcount]
  3276                              <1> 		; ecx and [u.pcount] are always > 0, here
  3277 00005873 39D1                <1> 	cmp	ecx, edx	
  3278 00005875 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3279                              <1> sioreg_2: ; 2:
  3280 00005877 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3281                              <1> sioreg_3:
  3282 00005879 010D[74700000]      <1> 	add 	[u.nread], ecx
  3283                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3284                              <1> 			         ; / during write is put into u.nread
  3285 0000587F 290D[70700000]      <1> 	sub 	[u.count], ecx
  3286                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3287                              <1> 			       ; / must be written or read
  3288 00005885 010D[6C700000]      <1> 	add 	[u.base], ecx
  3289                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3290                              <1> 			      ; / data bytes
  3291 0000588B 010E                <1>         add 	[esi], ecx 
  3292                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3293                              <1> 			       ; / + old file offset
  3294                              <1> 	; 25/07/2015
  3295 0000588D 8B35[AD700000]      <1> 	mov	esi, [u.pbase]
  3296 00005893 66290D[B1700000]    <1> 	sub	[u.pcount], cx
  3297 0000589A 010D[AD700000]      <1> 	add	[u.pbase], ecx
  3298 000058A0 C3                  <1>         retn
  3299                              <1> 		; rts r0
  3300                              <1> 		; transfer count > [u.pcount]
  3301                              <1> sioreg_4:
  3302                              <1> 	; 25/07/2015
  3303                              <1> 	; transfer count > [u.pcount] 
  3304                              <1> 	; (ecx > edx)
  3305 000058A1 89C8                <1> 	mov	eax, ecx
  3306 000058A3 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3307 000058A5 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3308 000058A7 EBD0                <1> 	jmp	short sioreg_3
  2108                                  %include 'u7.s'        ; 18/04/2015
  2109                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS7.INC
  2110                              <1> ; Last Modification: 13/06/2022
  2111                              <1> ; ----------------------------------------------------------------------------
  2112                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2113                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2114                              <1> ;
  2115                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2116                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2117                              <1> ; <Bell Laboratories (17/3/1972)>
  2118                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2119                              <1> ;
  2120                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2121                              <1> ;
  2122                              <1> ; ****************************************************************************
  2123                              <1> 
  2124                              <1> sysmount: ; / mount file system; args special; name
  2125                              <1> 	; 15/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2126                              <1> 	; 09/02/2022
  2127                              <1> 	; 08/02/2022
  2128                              <1> 	; 07/02/2022
  2129                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2130                              <1> 	; 14/11/2015
  2131                              <1> 	; 24/10/2015
  2132                              <1> 	; 13/10/2015
  2133                              <1> 	; 10/07/2015
  2134                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2135                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2136                              <1> 	;
  2137                              <1> 	; 'sysmount' anounces to the system that a removable 
  2138                              <1> 	; file system has been mounted on a special file.
  2139                              <1> 	; The device number of the special file is obtained via
  2140                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2141                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2142                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2143                              <1> 	; to read file system into core, i.e. the first block on the
  2144                              <1> 	; mountable file system is read in. This block is super block
  2145                              <1> 	; for the file system. This call is super user restricted.	
  2146                              <1> 	;
  2147                              <1> 	; Calling sequence:
  2148                              <1> 	;	sysmount; special; name
  2149                              <1> 	; Arguments:
  2150                              <1> 	;	special - pointer to name of special file (device)
  2151                              <1> 	;	name -  pointer to name of the root directory of the
  2152                              <1> 	;		newly mounted file system. 'name' should 
  2153                              <1> 	;		always be a directory.
  2154                              <1> 	; Inputs: - 
  2155                              <1> 	; Outputs: -
  2156                              <1> 	; ...............................................................
  2157                              <1> 	;				
  2158                              <1> 	; Retro UNIX 8086 v1 modification: 
  2159                              <1> 	;       'sysmount' system call has two arguments; so,
  2160                              <1> 	;	* 1st argument, special is pointed to by BX register
  2161                              <1> 	;	* 2nd argument, name is in CX register
  2162                              <1> 	;
  2163                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2164                              <1> 	;	       already modified for IBM PC compatibility and 
  2165                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2166                              <1> 	
  2167                              <1> 	;call	arg2
  2168                              <1> 		; jsr r0,arg2 / get arguments special and name
  2169 000058A9 891D[64700000]      <1> 	mov	[u.namep], ebx
  2170                              <1> 	; 09/02/2022
  2171                              <1> 	;push	ecx ; directory name
  2172 000058AF 66833D[34700000]00  <1> 	cmp	word [mnti], 0
  2173                              <1> 		; tst mnti / is the i-number of the cross device file
  2174                              <1> 			 ; / zero?
  2175                              <1> 	;;ja	error
  2176                              <1>         	; bne errora / no, error
  2177                              <1> 	;ja	sysmnt_err0
  2178                              <1> 	; 11/01/2022
  2179 000058B7 7605                <1> 	jna	short sysmnt_0
  2180 000058B9 E968010000          <1> 	jmp	sysmnt_err0
  2181                              <1> sysmnt_0:
  2182                              <1> 	; 09/02/2022
  2183 000058BE 51                  <1> 	push	ecx ; directory name
  2184 000058BF E84A010000          <1> 	call	getspl
  2185                              <1> 		; jsr r0,getspl / get special files device number in r1
  2186                              <1> 	; 09/02/2022
  2187 000058C4 8F05[64700000]      <1> 	pop	dword [u.namep] ; directory name
  2188                              <1> 	; 13/10/2015
  2189                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2190                              <1> 	; 11/01/2022
  2191 000058CA 29DB                <1> 	sub	ebx, ebx
  2192 000058CC 88C3                <1> 	mov	bl, al
  2193 000058CE F683[CA670000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2194 000058D5 750F                <1> 	jnz	short sysmnt_1
  2195                              <1> sysmnt_err1:
  2196 000058D7 C705[A1700000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2196 000058DF 0000                <1>
  2197 000058E1 E9D9E1FFFF          <1> 	jmp	error
  2198                              <1> sysmnt_1:
  2199                              <1> 	; 09/02/2022
  2200                              <1> 	;pop	dword [u.namep]
  2201                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2202                              <1> 				  ; / on the device
  2203                              <1> 	; 14/11/2015
  2204 000058E6 53                  <1> 	push	ebx ; 13/10/2015
  2205                              <1> 		; mov r1,-(sp) / save the device number
  2206                              <1>         ;
  2207 000058E7 E8E0F0FFFF          <1> 	call	namei
  2208                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2209                              <1> 		       ; ax = 0 -> file not found 	
  2210                              <1> 	;jz	error
  2211                              <1> 	;jc	error
  2212                              <1> 		; jsr r0,namei / get the i-number of the file
  2213                              <1>                	; br errora
  2214 000058EC 730F                <1> 	jnc	short sysmnt_2
  2215                              <1> sysmnt_err2:
  2216 000058EE C705[A1700000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2216 000058F6 0000                <1>
  2217 000058F8 E9C2E1FFFF          <1> 	jmp	error
  2218                              <1> sysmnt_2:	
  2219 000058FD 66A3[34700000]      <1> 	mov	[mnti], ax
  2220                              <1>         	; mov r1,mnti / put it in mnti
  2221                              <1> 
  2222                              <1> 	; 15/05/2022
  2223                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2224 00005903 66A1[2C700000]      <1> 	mov	ax, [ii]
  2225 00005909 66A3[36700000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2226                              <1> 
  2227                              <1> 	; 11/01/2022
  2228 0000590F BB[0C7F0000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2229                              <1> sysmnt_3: ;1:
  2230                              <1>         ;cmp	byte [ebx+1], 0
  2231                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2232                              <1> 			   ; / dismountable device set?
  2233                              <1>         ;jna	short sysmnt_4		
  2234                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2235                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2236                              <1> 	;jmp	short sysmnt_3
  2237                              <1> sysmnt_4:   
  2238 00005914 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2239 00005915 A2[31700000]        <1> 	mov	[mdev], al
  2240                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2241 0000591A 8803                <1> 	mov	[ebx], al
  2242                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2243                              <1> 			      ; / of the I/O queue entry
  2244                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2245                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2246 0000591C 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2247                              <1> 		; bis $2000,sb1 / set the read bit
  2248                              <1> 	; Retro UNIX 386 v1 modification : 
  2249                              <1> 	;	32 bit block number at buffer header offset 4
  2250 00005921 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2251 00005928 E859060000          <1> 	call 	diskio
  2252 0000592D 7345                <1> 	jnc	short sysmnt_5
  2253 0000592F 31C0                <1> 	xor 	eax, eax
  2254 00005931 66A3[34700000]      <1> 	mov	[mnti], ax ; 0
  2255 00005937 A2[31700000]        <1> 	mov	[mdev], al ; 0
  2256                              <1> 	;mov	[cdev], al ; 0
  2257                              <1> 	; 08/02/2022
  2258 0000593C 803D[B4700000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2259 00005943 7508                <1> 	jne	short sysmnt_err3
  2260                              <1> 	; yes, clear [u.brwdev] for next check
  2261                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2262 00005945 FE05[B4700000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2263 0000594B EB0A                <1> 	jmp	short sysmnt_err4
  2264                              <1> sysmnt_err3:	; 08/02/2022
  2265                              <1> 	; no, set [u.error] to disk read error
  2266 0000594D C705[A1700000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2266 00005955 0000                <1>
  2267                              <1> sysmnt_err4:
  2268                              <1> 	; 08/02/2022
  2269                              <1> 	; 14/11/2015
  2270 00005957 FEC8                <1> 	dec 	al
  2271 00005959 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2272 0000595B FEC0                <1> 	inc	al
  2273 0000595D 48                  <1> 	dec	eax
  2274 0000595E 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2275 00005961 E959E1FFFF          <1> 	jmp	error
  2276                              <1> sysmnt_invd:
  2277                              <1> 	; 08/02/2022
  2278 00005966 C705[A1700000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2278 0000596E 0000                <1>
  2279                              <1> 				 ;'invalid fs/superblock !' error
  2280 00005970 30C0                <1> 	xor	al, al
  2281 00005972 EBE3                <1> 	jmp	short sysmnt_err4	
  2282                              <1> 
  2283                              <1> sysmnt_5:
  2284                              <1> 	; 08/02/2022
  2285                              <1> 	; 11/01/2022 (BugFix)
  2286                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2287                              <1> 	; (Following check is needed to prevent mounting an
  2288                              <1> 	; invalid file system (invalid super block).
  2289                              <1> 	; 
  2290 00005974 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2291 00005977 C0E002              <1> 	shl	al, 2 ; 4*index
  2292 0000597A 8B88[AE670000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2293 00005980 C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2294                              <1> 	; ecx = number of free map bytes (required)
  2295                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2296 00005983 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2297                              <1> 	; edx = number of free blocks map bytes
  2298                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2299                              <1> 	; 07/02/2022
  2300                              <1> 	;xor	al, al ; 08/02/2022
  2301 00005987 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2302                              <1> 			 ; (in sectors), if they are not equal
  2303                              <1> 			 ; the disk to be mounted is an...	
  2304 00005989 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2305                              <1> 			 ; (which has not got a valid super block)
  2306                              <1> 	;
  2307 0000598B C6430100            <1> 	mov	byte [ebx+1], 0
  2308                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2309                              <1> ;sysmnt_6: ;1:
  2310                              <1> 	;;cmp	byte [sb1+1], 0
  2311                              <1> 		; tstb sb1+1 / done reading?
  2312                              <1>    	;;jna	sysret
  2313                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2314                              <1> 	;;jmp	short sysmnt_6
  2315                              <1> 		; bne 1b / no, wait
  2316                              <1>         	; br sysreta / yes
  2317 0000598F E94BE1FFFF          <1> 	jmp	sysret
  2318                              <1> 
  2319                              <1> sysumount: ; / special dismount file system
  2320                              <1> 	; 15/05/2022
  2321                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2322                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2323                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2324                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2325                              <1> 	;
  2326                              <1> 	; 04/11/2013
  2327                              <1> 	; 09/07/2013
  2328                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2329                              <1> 	; indicated as an argument is no longer contain a removable
  2330                              <1> 	; file system. 'getspl' gets the device number of the special
  2331                              <1> 	; file. If no file system was mounted on that device an error
  2332                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2333                              <1> 	; to 'sysret'.
  2334                              <1> 	;
  2335                              <1> 	; Calling sequence:
  2336                              <1> 	;	sysmount; special
  2337                              <1> 	; Arguments:
  2338                              <1> 	;	special - special file to dismount (device)
  2339                              <1> 	;
  2340                              <1> 	; Inputs: - 
  2341                              <1> 	; Outputs: -
  2342                              <1> 	; ...............................................................
  2343                              <1> 	;				
  2344                              <1> 	; Retro UNIX 8086 v1 modification: 
  2345                              <1> 	;       'sysumount' system call has one argument; so,
  2346                              <1> 	;	* Single argument, special is pointed to by BX register
  2347                              <1> 	;
  2348                              <1> 	
  2349                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2350                              <1> 	;call	arg
  2351                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2352 00005994 891D[64700000]      <1>         mov	[u.namep], ebx
  2353 0000599A E86F000000          <1> 	call	getspl
  2354                              <1> 		; jsr r0,getspl / get the device number in r1
  2355                              <1> 
  2356                              <1> 	;;;
  2357                              <1> 	; 09/05/2022 - Erdogan Tan
  2358                              <1> 	; (I have added [mnti] check because
  2359                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2360                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2361                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2362                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2363 0000599F 66833D[34700000]00  <1> 	cmp	word [mnti], 0
  2364 000059A7 767D                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2365                              <1> 	;;;
  2366                              <1> 
  2367 000059A9 3A05[31700000]      <1> 	cmp	al, [mdev]
  2368                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2369 000059AF 7575                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2370                              <1> 	;jne	error
  2371                              <1>         	; bne errora / no error
  2372 000059B1 30C0                <1> 	xor	al, al ; ah = 0
  2373                              <1> sysumnt_0: ;1:
  2374                              <1>      	; 11/01/2022
  2375                              <1> 	;cmp 	[sb1+1], al ; 0
  2376                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2377                              <1> 	;		   ; / (inhibit bit set)?
  2378                              <1> 	;jna	short sysumnt_1		
  2379                              <1> 	;	; bne 1b / yes, wait
  2380                              <1> 	;call	idle ; (wait for hardware interrupt)
  2381                              <1> 	;jmp	short sysumnt_0
  2382                              <1> sysumnt_1:        
  2383                              <1> 	; 15/05/2022
  2384                              <1> 	; change user's current directory to mounting directory
  2385                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2386 000059B3 3805[96700000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2387 000059B9 7643                <1> 	jna	short sysumnt_4
  2388                              <1> 	;;;
  2389                              <1> 	; 15/05/2022
  2390                              <1> 	; It is needed to change the parent process's current
  2391                              <1> 	; directory because shell runs (/etc/umount) 
  2392                              <1> 	; as child process.
  2393 000059BB 31DB                <1> 	xor	ebx, ebx 
  2394 000059BD 8A1D[9B700000]      <1> 	mov	bl, [u.uno]
  2395 000059C3 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2396 000059C5 81C3[866D0000]      <1> 	add	ebx, p.ppid-2
  2397 000059CB 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2398 000059CE BE[686D0000]        <1> 	mov	esi, p.pid
  2399 000059D3 29C9                <1> 	sub	ecx, ecx
  2400 000059D5 B110                <1> 	mov	cl, nproc ; 16  
  2401                              <1> sysumnt_2:	
  2402 000059D7 66AD                <1> 	lodsw
  2403 000059D9 6639D0              <1> 	cmp	ax, dx
  2404 000059DC 7402                <1> 	je	short sysumnt_3
  2405 000059DE E2F7                <1> 	loop	sysumnt_2
  2406                              <1> sysumnt_3:
  2407 000059E0 31C0                <1> 	xor	eax, eax
  2408 000059E2 81EE[686D0000]      <1> 	sub	esi, p.pid
  2409 000059E8 D1E6                <1> 	shl	esi, 1
  2410 000059EA 8B9E[D46D0000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2411                              <1> 	; ebx points to user (u) structure in upage
  2412 000059F0 668B15[34700000]    <1> 	mov	dx, [mnti]
  2413                              <1> 	;mov	[u.cdir], dx
  2414                              <1> 	;mov	[u.cdrv], al ; 0
  2415 000059F7 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2416 000059FB 884352              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2417                              <1> 	;;;
  2418                              <1> sysumnt_4: 
  2419 000059FE A2[31700000]        <1> 	mov	[mdev], al ; 0
  2420                              <1> 	     	; clr mntd / no, clear these
  2421 00005A03 66A3[34700000]      <1>    	mov	[mnti], ax ; 0
  2422                              <1>         	; clr mnti
  2423                              <1> 
  2424                              <1> 	;; 15/05/2022
  2425                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2426                              <1> 	;mov	ax, dx  ; [u.cdir]
  2427                              <1> 	;call	iget
  2428                              <1> 
  2429 00005A09 E9D1E0FFFF          <1>         jmp	sysret
  2430                              <1> 		; br sysreta / return
  2431                              <1> 
  2432                              <1> getspl: ; / get device number from a special file name
  2433 00005A0E E8B9EFFFFF          <1> 	call	namei
  2434                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2435                              <1> 		       ; ax = 0 -> file not found 	
  2436                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2437                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2438 00005A13 7305                <1> 	jnc	short getspl_0
  2439 00005A15 E9D4FEFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2440                              <1> getspl_0:
  2441                              <1> 	;jz	error
  2442                              <1> 	;jc	error
  2443                              <1> 		; jsr r0,namei / get the i-number of the special file
  2444                              <1>                 ; br errora / no such file
  2445 00005A1A 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2446                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2447                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2448 00005A1E 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2449                              <1> 	;jc	error
  2450                              <1> 		; ble errora / less than 0?  yes, error
  2451 00005A20 6683F805            <1>         cmp	ax, 5 ;
  2452                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2453                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2454                              <1> 	;;ja	error
  2455                              <1> 		; bgt errora / yes, error
  2456                              <1> 	; 11/01/2022
  2457 00005A24 760F                <1> 	jna	short getspl_retn
  2458                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2459                              <1> ;iopen_retn:
  2460                              <1> ;	retn
  2461                              <1> 		; rts r0 / return with device number in r1
  2462                              <1> sysmnt_err0:
  2463 00005A26 C705[A1700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2463 00005A2E 0000                <1>
  2464 00005A30 E98AE0FFFF          <1> 	jmp	error
  2465                              <1> 
  2466                              <1> getspl_retn:
  2467                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2468                              <1> 	; 11/01/2022
  2469                              <1> iopen_retn:
  2470 00005A35 C3                  <1> 	retn
  2471                              <1> 
  2472                              <1> iopen:	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2473                              <1> 	;		(Printer initialization)
  2474                              <1> 	; 11/01/2022
  2475                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2476                              <1> 	; 19/05/2015
  2477                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2478                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2479                              <1> 	;
  2480                              <1> 	; open file whose i-number is in r1
  2481                              <1> 	; 
  2482                              <1> 	; INPUTS ->
  2483                              <1> 	;    r1 - inode number
  2484                              <1> 	; OUTPUTS ->
  2485                              <1> 	;    file's inode in core	
  2486                              <1> 	;    r1 - inode number (positive)
  2487                              <1> 	;
  2488                              <1> 	; ((AX = R1))
  2489                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2490                              <1> 	;        
  2491                              <1> ; / open file whose i-number is in r1
  2492 00005A36 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2493                              <1> 		; tst r1 / write or read access?
  2494 00005A39 7568                <1>         jnz	short iopen_2
  2495                              <1> 		; blt 2f / write, go to 2f
  2496 00005A3B B202                <1> 	mov	dl, 2 ; read access
  2497 00005A3D E86EF8FFFF          <1> 	call	access
  2498                              <1>         	; jsr r0,access; 2 
  2499                              <1> 	; / get inode into core with read access
  2500                              <1> 	; DL=2
  2501                              <1> iopen_0:
  2502 00005A42 6683F828            <1>         cmp	ax, 40
  2503                              <1> 		; cmp r1,$40. / is it a special file
  2504 00005A46 77ED                <1>         ja	short iopen_retn
  2505                              <1> 		; bgt  3f / no. 3f
  2506 00005A48 50                  <1> 	push	eax ; 08/01/2022
  2507                              <1> 	;push	ax
  2508                              <1> 		; mov r1,-(sp) / yes, figure out
  2509 00005A49 0FB6D8              <1> 	movzx	ebx, al
  2510 00005A4C C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2511                              <1> 	;shl	bx, 2
  2512                              <1> 		; asl r1
  2513 00005A4F 81C3[535A0000]      <1>         add     ebx, iopen_1 - 4
  2514 00005A55 FF23                <1> 	jmp	dword [ebx]
  2515                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2516                              <1> iopen_1: ; 1:
  2517 00005A57 [BB5A0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2518                              <1>  		 ;otty / tty ; r1=2
  2519                              <1>         	 ;oppt / ppt ; r1=4
  2520 00005A5B [735B0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2521                              <1> 		 ;sret / mem ; r1=6
  2522                              <1> 		 ;sret / rf0
  2523                              <1>         	 ;sret / rk0
  2524                              <1>         	 ;sret / tap0
  2525                              <1>         	 ;sret / tap1
  2526                              <1>         	 ;sret / tap2
  2527                              <1>         	 ;sret / tap3
  2528                              <1>         	 ;sret / tap4
  2529                              <1>         	 ;sret / tap5
  2530                              <1>         	 ;sret / tap6
  2531                              <1>         	 ;sret / tap7
  2532 00005A5F [735B0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2533 00005A63 [735B0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2534 00005A67 [735B0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2535 00005A6B [735B0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2536 00005A6F [735B0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2537 00005A73 [735B0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2538                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2539                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2540                              <1> 	; 13/06/2022 - (lpt_init)
  2541 00005A77 [3F5C0000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2542 00005A7B [CC5A0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2543                              <1> 		 ;ocvt / tty0
  2544 00005A7F [CC5A0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2545                              <1> 		 ;ocvt / tty1
  2546 00005A83 [CC5A0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2547                              <1> 		 ;ocvt / tty2
  2548 00005A87 [CC5A0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2549                              <1> 		 ;ocvt / tty3
  2550 00005A8B [CC5A0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2551                              <1> 		 ;ocvt / tty4
  2552 00005A8F [CC5A0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2553                              <1> 		 ;ocvt / tty5
  2554 00005A93 [CC5A0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2555                              <1> 		 ;ocvt / tty6
  2556 00005A97 [CC5A0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2557                              <1> 		 ;ocvt / tty7
  2558 00005A9B [CC5A0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2559                              <1> 		 ;error / crd
  2560 00005A9F [CC5A0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2561                              <1> 
  2562                              <1> iopen_2: ; 2: / check open write access
  2563 00005AA3 66F7D8              <1> 	neg	ax
  2564                              <1> 		;neg r1 / make inode number positive
  2565 00005AA6 B201                <1> 	mov	dl, 1 ; write access
  2566 00005AA8 E803F8FFFF          <1> 	call	access
  2567                              <1> 		;jsr r0,access; 1 / get inode in core
  2568                              <1> 	; DL=1
  2569                              <1> 	; 11/01/2022
  2570 00005AAD F605[496D0000]40    <1> 	test	byte [i.flgs+1], 40h
  2571                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2572                              <1>  		; bit $40000,i.flgs / is it a directory?
  2573 00005AB4 748C                <1> 	jz	short iopen_0
  2574                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2575                              <1> 	;jmp	error ; permission denied !
  2576 00005AB6 E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2577                              <1> 	;;jnz	error		
  2578                              <1>        		; bne 2f / yes, transfer (error)
  2579                              <1>         ;;jmp	short iopen_0
  2580                              <1> 	;cmp	ax, 40
  2581                              <1> 		; cmp r1,$40. / no, is it a special file?
  2582                              <1>         ;ja	short iopen_2
  2583                              <1> 		; bgt 3f / no, return
  2584                              <1> 	;push	ax
  2585                              <1> 		; mov r1,-(sp) / yes
  2586                              <1> 	;movzx	ebx, al
  2587                              <1> 	;shl	bx, 1
  2588                              <1> 		; asl r1
  2589                              <1> 	;add	ebx, ipen_3 - 2
  2590                              <1> 	;jmp	dword [ebx]
  2591                              <1> 		; jmp *1f-2(r1) / figure out 
  2592                              <1> 			; / which special file it is and transfer
  2593                              <1> ;iopen_3: ; 1:
  2594                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2595                              <1>  		 ;otty / tty ; r1=2
  2596                              <1>         	 ;leadr / ppt ; r1=4
  2597                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2598                              <1> 		 ;sret / mem ; r1=6
  2599                              <1> 		 ;sret / rf0
  2600                              <1>         	 ;sret / rk0
  2601                              <1>         	 ;sret / tap0
  2602                              <1>         	 ;sret / tap1
  2603                              <1>         	 ;sret / tap2
  2604                              <1>         	 ;sret / tap3
  2605                              <1>         	 ;sret / tap4
  2606                              <1>         	 ;sret / tap5
  2607                              <1>         	 ;sret / tap6
  2608                              <1>         	 ;sret / tap7
  2609                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2610                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2611                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2612                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2613                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2614                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2615                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2616                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2617                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2618                              <1> 		 ;ocvt / tty0
  2619                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2620                              <1> 		 ;ocvt / tty1
  2621                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2622                              <1> 		 ;ocvt / tty2
  2623                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2624                              <1> 		 ;ocvt / tty3
  2625                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2626                              <1> 		 ;ocvt / tty4
  2627                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2628                              <1> 		 ;ocvt / tty5
  2629                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2630                              <1> 		 ;ocvt / tty6
  2631                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2632                              <1> 		 ;ocvt / tty7
  2633                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2634                              <1> 		 ;/ ejec / lpr
  2635                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2636                              <1> 
  2637                              <1> otty: ;/ open console tty for reading or writing
  2638                              <1> 	; 03/03/2022
  2639                              <1> 	; 02/03/2022
  2640                              <1> 	; 26/02/2022
  2641                              <1> 	; 09/02/2022
  2642                              <1> 	; 06/02/2022
  2643                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2644                              <1> 	; 16/11/2015
  2645                              <1> 	; 12/11/2015
  2646                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2647                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2648                              <1> 	; 16/07/2013
  2649                              <1> 	; Retro UNIX 8086 v1 modification:
  2650                              <1> 	;  If a tty is open for read or write by
  2651                              <1> 	;     a process (u.uno), only same process can open
  2652                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2653                              <1> 	;
  2654                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2655                              <1> 	;
  2656 00005ABB 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2657 00005AC2 8A83[A76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2658                              <1> 	; 13/01/2014
  2659                              <1> 	;jmp	short ottyp
  2660                              <1> 	; 26/02/2022
  2661 00005AC8 88C4                <1> 	mov	ah, al
  2662 00005ACA EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2663                              <1> ocvt:
  2664 00005ACC 2C0A                <1> 	sub	al, 10
  2665                              <1> ;ottyp:	; (call from sysstty)
  2666                              <1> 	; 08/01/2022
  2667 00005ACE 31DB                <1> 	xor	ebx, ebx
  2668                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2669                              <1> 	; 26/02/2022
  2670 00005AD0 B4FF                <1> 	mov	ah, 0FFh
  2671                              <1> ottypc:
  2672                              <1> 	; 03/03/2022
  2673                              <1> 	; 26/02/2022
  2674                              <1> 	; 09/02/2022
  2675                              <1> 	; 08/01/2022
  2676                              <1> 	; 16/11/2015
  2677                              <1> 	; 12/11/2015
  2678                              <1> 	; 18/05/2015 (32 bit modifications)
  2679                              <1> 	; 06/12/2013 - 13/07/2014
  2680 00005AD2 88C6                <1> 	mov	dh, al ; tty number
  2681                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2682                              <1> 	; 08/01/2022
  2683 00005AD4 88C3                <1> 	mov	bl, al
  2684 00005AD6 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2685                              <1> 	; 26/01/2014	
  2686 00005AD8 81C3[D46C0000]      <1> 	add 	ebx, ttyl
  2687 00005ADE 668B0B              <1> 	mov 	cx, [ebx]
  2688                              <1> 		   ; CL = lock value (0 or process number)
  2689                              <1> 		   ; CH = open count 
  2690 00005AE1 20C9                <1> 	and 	cl, cl
  2691                              <1> 	; 13/01/2014
  2692                              <1> 	;jz 	short otty_ret
  2693                              <1> 	; 08/01/2022
  2694 00005AE3 7447                <1> 	jz 	short ottys_0
  2695                              <1> 	;
  2696                              <1> 	; 16/11/2015
  2697 00005AE5 3A0D[9B700000]      <1> 	cmp 	cl, [u.uno]
  2698 00005AEB 746E                <1> 	je	short ottys_3
  2699                              <1> 	;
  2700                              <1> 	;
  2701                              <1> 	; 26/02/2022
  2702                              <1> 	; (is it the console tty of the current process?)
  2703                              <1> 	; ((fast check/permit for console tty open function))
  2704 00005AED 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2705 00005AEF 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2706                              <1> 	;
  2707                              <1> 	; 26/02/2022
  2708                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2709                              <1> 	;shl 	bl, 1
  2710                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2711                              <1> 	;;movzx ebx, byte [u.uno]
  2712                              <1> 	;mov	bl, [u.uno]
  2713                              <1> 	;shl 	bl, 1
  2714                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2715                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2716                              <1> 	; 26/02/2022 (BugFix) ; *
  2717 00005AF1 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2718 00005AF4 D1E6                <1> 	shl 	esi, 1
  2719 00005AF6 668B86[666D0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2720 00005AFD 96                  <1> 	xchg	esi, eax
  2721 00005AFE A0[9B700000]        <1> 	mov	al, [u.uno]
  2722 00005B03 D0E0                <1> 	shl 	al, 1
  2723 00005B05 663BB0[866D0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2724 00005B0C 744D                <1> 	je 	short ottys_3 ; *
  2725                              <1> 	; 26/02/2022
  2726                              <1> 	; check console tty of the process
  2727                              <1> 	; (open permission must be given if the -requested- tty is
  2728                              <1> 	;  console tty of current process)
  2729 00005B0E D0E8                <1> 	shr	al, 1
  2730 00005B10 38B0[A76D0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2731 00005B16 7443                <1> 	je 	short ottys_3
  2732                              <1> 	;
  2733                              <1> 	; the tty is locked by another process
  2734                              <1> 	; except the parent process (p.ppid)
  2735                              <1>         ;
  2736                              <1> 	; 09/02/2022
  2737                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2738                              <1> 	;		; permission denied ! error
  2739                              <1> otty_err: ; 13/01/2014
  2740                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2741                              <1> 	;;jnz	error
  2742                              <1> 	; 05/12/2021
  2743                              <1> 	;jz	short otty_stc_retn
  2744                              <1> 	;jmp	error
  2745                              <1> 	; 09/02/2022
  2746 00005B18 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2747 00005B1B 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2748                              <1> 	; iopen (dl=1 or dl=2)
  2749 00005B1D C705[A1700000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2749 00005B25 0000                <1>
  2750                              <1> 			; permission denied ! error
  2751 00005B27 E993DFFFFF          <1> 	jmp	error
  2752                              <1> ;otty_stc_retn:
  2753                              <1> 	;stc
  2754                              <1> 	;retn
  2755                              <1> ottys_0:
  2756                              <1> 	; 08/01/2022
  2757                              <1> otty_ret: 
  2758                              <1> 	; 13/01/2014
  2759 00005B2C 80FE07              <1> 	cmp 	dh, 7
  2760 00005B2F 7624                <1> 	jna	short ottys_2
  2761                              <1> 	; 16/11/2015
  2762                              <1> com_port_check:
  2763 00005B31 BE[F26C0000]        <1> 	mov	esi, com1p
  2764 00005B36 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2765 00005B39 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2766 00005B3B 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2767                              <1> ottys_1:
  2768                              <1> 	; 12/11/2015
  2769 00005B3C 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2770 00005B3F 7714                <1> 	ja	short com_port_ready
  2771                              <1> 	;
  2772                              <1> 	; 09/02/2022
  2773 00005B41 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2774 00005B44 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2775 00005B46 C705[A1700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2775 00005B4E 0000                <1>
  2776                              <1> 			   ; device not ready ! error
  2777                              <1> 	;jmp	short otty_err
  2778 00005B50 E96ADFFFFF          <1> 	jmp	error
  2779                              <1> com_port_ready:
  2780                              <1> ottys_2:
  2781                              <1> 	; 02/03/2022
  2782                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2783                              <1> 	;jnz	short ottys_3
  2784 00005B55 8A0D[9B700000]      <1> 	mov	cl, [u.uno]
  2785                              <1> ottys_3:
  2786 00005B5B FEC5                <1> 	inc 	ch
  2787 00005B5D 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2788                              <1> 	; 06/12/2013
  2789 00005B60 FEC6                <1> 	inc	dh ; tty number + 1
  2790 00005B62 BB[7C700000]        <1> 	mov	ebx, u.ttyp
  2791                              <1> 	; 13/01/2014
  2792 00005B67 F6C202              <1> 	test	dl, 2 ; open for read sign
  2793 00005B6A 7501                <1> 	jnz	short ottys_4
  2794 00005B6C 43                  <1> 	inc	ebx
  2795                              <1> ottys_4:
  2796                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2797 00005B6D 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2798                              <1> 	; 09/02/2022
  2799 00005B6F 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2800 00005B71 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2801                              <1> sret:
  2802                              <1> 	;pop 	ax
  2803 00005B73 58                  <1> 	pop	eax ; 08/01/2022
  2804                              <1> otty_retn:	; 09/02/2022
  2805                              <1> iclose_retn:	
  2806 00005B74 C3                  <1> 	retn
  2807                              <1> 
  2808                              <1> 	;
  2809                              <1> 	; Original UNIX v1 'otty' routine:
  2810                              <1> 	;	
  2811                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2812                              <1>         ;                 / reader status reg
  2813                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2814                              <1>         ;                 / punch status reg
  2815                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2816                              <1>         ;                          / console tty buffer
  2817                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2818                              <1>         ;            / console tty
  2819                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2820                              <1>         ;             / buffer header
  2821                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2822                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2823                              <1>         ;                 / tty
  2824                              <1>         ;br     sret / ?
  2825                              <1> ;sret:
  2826                              <1> 		;clr *$ps / set processor priority to zero
  2827                              <1> ;	pop	ax
  2828                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2829                              <1> ;3:
  2830                              <1> ;	retn
  2831                              <1>         	;rts r0
  2832                              <1> 	
  2833                              <1> ;ocvt:	; < open tty >
  2834                              <1> 	; 13/01/2014
  2835                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2836                              <1> 	; 24/09/2013 consistency check -> ok
  2837                              <1> 	; 16/09/2013
  2838                              <1> 	; 03/09/2013
  2839                              <1> 	; 27/08/2013
  2840                              <1> 	; 16/08/2013
  2841                              <1> 	; 16/07/2013
  2842                              <1> 	; 27/05/2013
  2843                              <1> 	; 21/05/2013
  2844                              <1> 	;
  2845                              <1> 	; Retro UNIX 8086 v1 modification !
  2846                              <1> 	; 
  2847                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2848                              <1> 	;	(exactly different than this one)
  2849                              <1> 	;	was in 'u9.s' file.
  2850                              <1> 	;
  2851                              <1> 	; 16/07/2013
  2852                              <1> 	; Retro UNIX 8086 v1 modification:
  2853                              <1> 	;  If a tty is open for read or write by
  2854                              <1> 	;     a process (u.uno), only same process can open
  2855                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2856                              <1> 	;
  2857                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2858                              <1> 
  2859                              <1> 	; 16/09/2013
  2860                              <1> 	; sub 	al, 10
  2861                              <1> 	
  2862                              <1> 	; 06/12/2013
  2863                              <1> 	;cmp	al, 7
  2864                              <1>         ;jna     short ottyp
  2865                              <1> 	; 13/01/2014
  2866                              <1> 	;jmp	short ottyp
  2867                              <1> 
  2868                              <1> ;oppt: / open paper tape for reading or writing
  2869                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2870                              <1> ;        tstb   pptiflg / is file already open
  2871                              <1> ;        bne    2f / yes, branch
  2872                              <1> ;1:
  2873                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2874                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2875                              <1> ;               br .+4 / for paper tape input and place in free list
  2876                              <1> ;        br     1b
  2877                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2878                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2879                              <1> ;        br     sret
  2880                              <1> ;2:
  2881                              <1> ;        jmp    error / file already open
  2882                              <1> 
  2883                              <1> iclose:
  2884                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2885                              <1> 	; 19/05/2015
  2886                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2887                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2888                              <1> 	;
  2889                              <1> 	; close file whose i-number is in r1
  2890                              <1> 	; 
  2891                              <1> 	; INPUTS ->
  2892                              <1> 	;    r1 - inode number
  2893                              <1> 	; OUTPUTS ->
  2894                              <1> 	;    file's inode in core	
  2895                              <1> 	;    r1 - inode number (positive)
  2896                              <1> 	;
  2897                              <1> 	; ((AX = R1))
  2898                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2899                              <1> 	;        
  2900                              <1> ;/ close file whose i-number is in r1
  2901 00005B75 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2902 00005B77 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2903                              <1> 		; tst r1 / test i-number
  2904                              <1>         ;jnz	short iclose_2
  2905                              <1> 		; blt 2f / if neg., branch
  2906 00005B7A 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2907                              <1> 	; 16/07/2013 
  2908 00005B7C 66F7D8              <1> 	neg	ax ; make it positive
  2909                              <1> 	; 12/01/2014
  2910 00005B7F FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2911                              <1> iclose_0:
  2912 00005B81 6683F828            <1> 	cmp	ax, 40
  2913                              <1> 		; cmp r1,$40. / is it a special file
  2914 00005B85 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2915                              <1> 		; bgt 3b / no, return
  2916                              <1> 	; 12/01/2014
  2917                              <1> 	; DL=2 -> special file was opened for reading
  2918                              <1> 	; DL=1 -> special file was opened for writing
  2919 00005B87 50                  <1> 	push	eax ; 08/01/2022
  2920                              <1> 	;push	ax
  2921                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2922 00005B88 0FB6D8              <1> 	movzx	ebx, al
  2923                              <1> 	; 08/01/2022
  2924 00005B8B C0E302              <1> 	shl	bl, 2
  2925                              <1> 	;shl	bx, 2
  2926                              <1> 		; asl r1
  2927 00005B8E 81C3[925B0000]      <1> 	add	ebx, iclose_1 - 4
  2928 00005B94 FF23                <1> 	jmp	dword [ebx]
  2929                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2930                              <1> iclose_1 :
  2931 00005B96 [E25B0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2932 00005B9A [3D5C0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2933 00005B9E [3D5C0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2934 00005BA2 [3D5C0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2935 00005BA6 [3D5C0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2936 00005BAA [3D5C0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2937 00005BAE [3D5C0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2938 00005BB2 [3D5C0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2939 00005BB6 [3D5C0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2940                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2941                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2942 00005BBA [F15B0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2943 00005BBE [F15B0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2944 00005BC2 [F15B0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2945 00005BC6 [F15B0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2946 00005BCA [F15B0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2947 00005BCE [F15B0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2948 00005BD2 [F15B0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2949 00005BD6 [F15B0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2950 00005BDA [F15B0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2951 00005BDE [F15B0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2952                              <1> 
  2953                              <1> 	; 1:
  2954                              <1> 	;        ctty   / tty
  2955                              <1> 	;        cppt   / ppt
  2956                              <1> 	;        sret   / mem
  2957                              <1> 	;        sret   / rf0
  2958                              <1> 	;        sret   / rk0
  2959                              <1> 	;        sret   / tap0
  2960                              <1> 	;        sret   / tap1
  2961                              <1> 	;        sret   / tap2
  2962                              <1> 	;        sret   / tap3
  2963                              <1> 	;        sret   / tap4
  2964                              <1> 	;        sret   / tap5
  2965                              <1> 	;        sret   / tap6
  2966                              <1> 	;        sret   / tap7
  2967                              <1> 	;        ccvt   / tty0
  2968                              <1> 	;        ccvt   / tty1
  2969                              <1> 	;        ccvt   / tty2
  2970                              <1> 	;        ccvt   / tty3
  2971                              <1> 	;        ccvt   / tty4
  2972                              <1> 	;        ccvt   / tty5
  2973                              <1> 	;        ccvt   / tty6
  2974                              <1> 	;        ccvt   / tty7
  2975                              <1> 	;        error / crd
  2976                              <1> 
  2977                              <1> ;iclose_2: ; 2: / negative i-number
  2978                              <1> 	;neg	ax
  2979                              <1> 		;neg r1 / make it positive
  2980                              <1> 	;cmp	ax, 40
  2981                              <1> 		;cmp r1,$40. / is it a special file?
  2982                              <1>         ;ja	short @b
  2983                              <1> 		;bgt    3b / no. return
  2984                              <1> 	;push	ax
  2985                              <1> 		;mov r1,-(sp)
  2986                              <1> 	;movzx	ebx, al
  2987                              <1> 	;shl	bx, 1
  2988                              <1> 		;asl r1 / yes. compute jump address and transfer
  2989                              <1> 	;add	ebx, iclose_3 - 2
  2990                              <1> 	;jmp	dword [ebx]
  2991                              <1> 		;jmp *1f-2(r1) / figure out 
  2992                              <1> ;iclose_3:
  2993                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2994                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2995                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2996                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2997                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2998                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2999                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3000                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3001                              <1> 	 ;dd	sret ; lpr, AX = 9	
  3002                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3003                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3004                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3005                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3006                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3007                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3008                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3009                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3010                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3011                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3012                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3013                              <1> 	
  3014                              <1> 	;1:
  3015                              <1> 	;      	ctty   / tty
  3016                              <1> 	;       leadr  / ppt
  3017                              <1> 	;       sret   / mem
  3018                              <1> 	;       sret   / rf0
  3019                              <1> 	;       sret   / rk0
  3020                              <1> 	;       sret   / tap0
  3021                              <1> 	;       sret   / tap1
  3022                              <1> 	;       sret   / tap2
  3023                              <1> 	;       sret   / tap3
  3024                              <1> 	;       sret   / tap4
  3025                              <1> 	;       sret   / tap5
  3026                              <1> 	;       sret   / tap6
  3027                              <1> 	;       sret   / tap7
  3028                              <1> 	;       ccvt   / tty0
  3029                              <1> 	;       ccvt   / tty1
  3030                              <1> 	;       ccvt   / tty2
  3031                              <1> 	;       ccvt   / tty3
  3032                              <1> 	;       ccvt   / tty4
  3033                              <1> 	;       ccvt   / tty5
  3034                              <1> 	;       ccvt   / tty6
  3035                              <1> 	;       ccvt   / tty7
  3036                              <1> 	;/      ejec   / lpr
  3037                              <1> 
  3038                              <1> ctty: ; / close console tty
  3039                              <1> 	; 26/02/2022
  3040                              <1> 	; 09/02/2022
  3041                              <1> 	; 06/02/2022
  3042                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3043                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3044                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3045                              <1> 	;
  3046                              <1> 	; Retro UNIX 8086 v1 modification !
  3047                              <1> 	; (DL = 2 -> it is open for reading)
  3048                              <1> 	; (DL = 1 -> it is open for writing)
  3049                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3050                              <1> 	;
  3051                              <1> 	; 06/12/2013
  3052 00005BE2 0FB61D[9B700000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3053 00005BE9 8A83[A76D0000]      <1>         mov     al, [ebx+p.ttyc-1]
  3054                              <1> 	; 13/01/2014
  3055                              <1> 	;jmp	short cttyp
  3056                              <1> 	; 06/02/2022
  3057 00005BEF EB04                <1> 	jmp	short ctty_0
  3058                              <1> ccvt:
  3059 00005BF1 2C0A                <1> 	sub 	al, 10
  3060                              <1> cttyp:	; (call from sysstty)
  3061                              <1> 	; 08/01/2022
  3062 00005BF3 31DB                <1> 	xor	ebx, ebx
  3063                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  3064                              <1> 	; 08/01/2022
  3065                              <1> 	; 18/05/2015 (32 bit modifications)
  3066                              <1> 	; 16/08/2013 - 26/01/2014
  3067                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3068                              <1> 	; 08/01/2022
  3069 00005BF5 88C3                <1> 	mov	bl, al
  3070 00005BF7 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3071                              <1> 	; 26/01/2014
  3072 00005BF9 81C3[D46C0000]      <1> 	add 	ebx, ttyl
  3073 00005BFF 88C6                <1> 	mov 	dh, al ; tty number
  3074 00005C01 668B03              <1> 	mov 	ax, [ebx]
  3075                              <1> 		   ; AL = lock value (0 or process number)
  3076                              <1> 		   ; AH = open count 
  3077 00005C04 20E4                <1> 	and 	ah, ah
  3078 00005C06 7514                <1> 	jnz	short ctty_ret
  3079                              <1>   	; 09/02/2022
  3080 00005C08 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3081 00005C0B 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3082                              <1> 	; iclose (dl=1 or dl=2)
  3083 00005C0D C705[A1700000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3083 00005C15 0000                <1>
  3084                              <1> 			; device not open ! error
  3085                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3086 00005C17 E9A3DEFFFF          <1> 	jmp	error
  3087                              <1> 	; 26/01/2014
  3088                              <1> ctty_ret:
  3089 00005C1C FECC                <1> 	dec 	ah ; decrease open count
  3090 00005C1E 7502                <1> 	jnz	short ctty_1
  3091 00005C20 30C0                <1> 	xor	al, al ; unlock/free tty
  3092                              <1> ctty_1:
  3093 00005C22 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3094                              <1> 	;
  3095 00005C25 BB[7C700000]        <1> 	mov	ebx, u.ttyp
  3096                              <1> 	;test	dl, 1 ; open for write sign
  3097                              <1> 	;jz	short ctty_2
  3098                              <1> 	; 26/02/2022
  3099 00005C2A F6C202              <1> 	test	dl, 2 ; open for read sign
  3100 00005C2D 7501                <1> 	jnz	short ctty_2
  3101 00005C2F 43                  <1> 	inc	ebx
  3102                              <1> ctty_2:
  3103 00005C30 FEC6                <1> 	inc	dh ; tty number + 1
  3104 00005C32 3A33                <1> 	cmp	dh, [ebx]
  3105                              <1> 	;jne	short cret
  3106 00005C34 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3107                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3108 00005C36 C60300              <1> 	mov	byte [ebx], 0
  3109                              <1> ctty_3:
  3110                              <1> 	; 09/02/2022
  3111 00005C39 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3112 00005C3B 7401                <1> 	jz	short ctty_4
  3113                              <1> cret:
  3114                              <1> 	;pop	ax
  3115                              <1> 	; 08/01/2022
  3116 00005C3D 58                  <1> 	pop	eax
  3117                              <1> ctty_stc_retn:	; 09/02/2022
  3118                              <1> ctty_4:
  3119 00005C3E C3                  <1> 	retn
  3120                              <1> 
  3121                              <1> ;ctty_err: ; 13/01/2014
  3122                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3123                              <1> ;	jnz	error
  3124                              <1> ;	stc
  3125                              <1> ;	retn
  3126                              <1> 
  3127                              <1> 	; Original UNIX v1 'ctty' routine:
  3128                              <1> 	;	
  3129                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3130                              <1> 	;		;/ point r5 to the console tty buffer
  3131                              <1>         ;decb   (r5) / dec number of processes using console tty
  3132                              <1>         ;br     sret / return via sret
  3133                              <1> 
  3134                              <1> ;ccvt:	; < close tty >
  3135                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3136                              <1> 	;
  3137                              <1> 	; Retro UNIX 8086 v1 modification !
  3138                              <1> 	; 
  3139                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3140                              <1> 	;		(exactly different than this one)
  3141                              <1> 	;	was in 'u9.s' file.
  3142                              <1> 	;
  3143                              <1> 	; DL = 2 -> it is open for reading
  3144                              <1> 	; DL = 1 -> it is open for writing
  3145                              <1> 	;
  3146                              <1> 	; 17/09/2013
  3147                              <1> 	;sub 	al, 10
  3148                              <1> 	;cmp	al, 7
  3149                              <1> 	;jna	short cttyp
  3150                              <1> 	; 13/01/2014
  3151                              <1> 	;jmp	short cttyp
  3152                              <1> 
  3153                              <1> ;cppt: / close paper tape
  3154                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3155                              <1> ;1:
  3156                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3157                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3158                              <1> ;                          / and assign to free list
  3159                              <1> ;               br sret
  3160                              <1> ;        br     1b
  3161                              <1> 
  3162                              <1> ;ejec:	
  3163                              <1> ;	jmp	error
  3164                              <1> ;/ejec:
  3165                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3166                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3167                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3168                              <1> ;/       br     sret / return to caller via 'sret'
  3169                              <1> 
  3170                              <1> ejec:
  3171                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  3172                              <1> 	;	     - Printer Initialization
  3173                              <1> lpt_init:	
  3174                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3175                              <1> 	;
  3176                              <1> 	; Default printer port: 378h ; LPT1
  3177                              <1> 	
  3178 00005C3F B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3179                              <1> 	;call	int17h
  3180 00005C41 E8C3FAFFFF          <1> 	call	PRNOP
  3181 00005C46 7414                <1> 	jz	short lpt_init_ok
  3182                              <1> 	
  3183                              <1> 	; replace error code with 'device not ready' error
  3184                              <1> 	; (this may be better for 'sysopen')
  3185 00005C48 B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3186 00005C4D A3[A1700000]        <1> 	mov	[u.error], eax
  3187                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3188 00005C52 A3[4C700000]        <1> 	mov	[u.r0], eax
  3189 00005C57 E963DEFFFF          <1> 	jmp	error ; (better)	
  3190                              <1> 	
  3191                              <1> lpt_init_ok:
  3192                              <1> 	;jmp	short cret
  3193 00005C5C 58                  <1> 	pop	eax    ; inode number
  3194 00005C5D C3                  <1> 	retn
  3195                              <1> 	
  2109                                  %include 'u8.s'        ; 11/06/2015
  2110                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS8.INC
  2111                              <1> ; Last Modification: 12/02/2022
  2112                              <1> ; ----------------------------------------------------------------------------
  2113                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2114                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2115                              <1> ;
  2116                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2117                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2118                              <1> ; <Bell Laboratories (17/3/1972)>
  2119                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2120                              <1> ;
  2121                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2122                              <1> ;
  2123                              <1> ; ****************************************************************************
  2124                              <1> 
  2125                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2126                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2127                              <1> ;; Word 1, byte 0 = device id
  2128                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2129                              <1> ;;          bit 9 = write bit
  2130                              <1> ;;	    bit 10 = read bit	  
  2131                              <1> ;;	    bit 12 = waiting to write bit	
  2132                              <1> ;;	    bit 13 = waiting to read bit
  2133                              <1> ;;	    bit 15 = inhibit bit
  2134                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2135                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2136                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2137                              <1> ;;
  2138                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2139                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2140                              <1> ;;
  2141                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2142                              <1> ;; Word 1, Byte 0 = device id
  2143                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2144                              <1> ;;          bit 9 = write bit
  2145                              <1> ;;	    bit 10 = read bit	  
  2146                              <1> ;;	    bit 12 = waiting to write bit	
  2147                              <1> ;;	    bit 13 = waiting to read bit
  2148                              <1> ;;	    bit 15 = inhibit bit
  2149                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2150                              <1> ;;
  2151                              <1> ;; Original UNIX v1 ->
  2152                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2153                              <1> ;; Original UNIX v1 -> 
  2154                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2155                              <1> ;;
  2156                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2157                              <1> ;;
  2158                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2159                              <1> ;;          0 = fd0
  2160                              <1> ;;	    1 = fd1
  2161                              <1> ;;	    2 = hd0
  2162                              <1> ;;	    3 = hd1
  2163                              <1> ;;	    4 = hd2
  2164                              <1> ;;	    5 = hd3
  2165                              <1> 
  2166                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2167                              <1> 
  2168                              <1> 	; 08/02/2022
  2169                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2170                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2171                              <1> 	; 26/04/2013
  2172                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2173                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2174                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2175                              <1> 
  2176                              <1> 	; 08/02/2022
  2177                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2178                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2179                              <1> 	; 26/04/2013
  2180                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2181                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2182                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2183                              <1> 
  2184                              <1> bread: 
  2185                              <1> 	; 08/02/2022
  2186                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2187                              <1> 	; 14/07/2015
  2188                              <1> 	; 10/07/2015
  2189                              <1> 	; 09/06/2015
  2190                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2191                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2192                              <1> 	;	
  2193                              <1> 	; / read a block from a block structured device
  2194                              <1> 	;
  2195                              <1> 	; INPUTS ->
  2196                              <1> 	;    [u.fofp] points to the block number
  2197                              <1> 	;    CX = maximum block number allowed on device
  2198                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2199                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2200                              <1> 	;    [u.count]	number of bytes to read in
  2201                              <1> 	; OUTPUTS ->
  2202                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2203                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2204                              <1> 	;
  2205                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2206                              <1> 	;
  2207                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2208                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2209                              <1> 	;	is increased by 1. For example: If user/program request 
  2210                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2211                              <1> 	;  	the next block number just as 512 byte reading is done.
  2212                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2213                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2214                              <1> 	;       enough to keep byte position/offset of the disk), this
  2215                              <1> 	;	defect will not be corrected, user/program must request
  2216                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2217                              <1> 	;       for achieving correct result. In future version(s), 
  2218                              <1> 	;	this defect will be corrected by using different 
  2219                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2220                              <1> 
  2221                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2222                              <1> 			       ; / (only works on tape)
  2223                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2224                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2225                              <1> ;1:
  2226                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2227                              <1> 			    ; / maximum block # allowed on device
  2228                              <1> 		; jnb short @f
  2229                              <1> 		; bhis	1f / yes, 1f (error)
  2230                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2231                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2232                              <1> 		; mov (sp)+,r1 / return block # to r1
  2233                              <1> 		; inc r1 / bump block # to next consecutive block
  2234                              <1> 		; dec (sp) / "2-1-cold" on stack
  2235                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2236                              <1> ;1:
  2237                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2238                              <1> 	;push	ecx ; **
  2239                              <1> 	; 26/04/2013
  2240                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2241 00005C5E 2C03                <1> 	sub	al, 3
  2242                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2243 00005C60 A2[B4700000]        <1> 	mov	[u.brwdev], al
  2244                              <1> 	; 09/06/2015
  2245                              <1> 	;movzx	ebx, al
  2246                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2247                              <1> 	; 12/01/2022 (BugFix)
  2248 00005C65 C0E002              <1> 	shl	al, 2 ; * 4
  2249 00005C68 8B88[AE670000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2250                              <1> bread_0:
  2251 00005C6E 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2252                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2253                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2254 00005C6F 8B1D[5C700000]      <1> 	mov	ebx, [u.fofp]
  2255 00005C75 8B03                <1> 	mov	eax, [ebx]
  2256 00005C77 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2257                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2258                              <1> 			       ; / block #
  2259 00005C7A 39C8                <1> 	cmp	eax, ecx
  2260                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2261                              <1>        	                     ; / block number allowed
  2262                              <1> 	;jnb	error 	     ; 18/04/2013
  2263                              <1> 		; bhis error10 / yes, error
  2264                              <1> 	; 08/02/2022
  2265                              <1> 	;jb	short bread_1
  2266                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2267                              <1> 	;jmp	error
  2268 00005C7C 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2269                              <1> bread_1:
  2270                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2271                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2272                              <1> 	; eAX = Block number (zero based)
  2273                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2274                              <1> preread: ;; call preread
  2275 00005C7E BF[B4700000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2276 00005C83 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2277                              <1> 	;; jc 	error
  2278                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2279                              <1>         ; eAX = Block/Sector number (r1)
  2280                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2281                              <1> 	; 14/03/2013
  2282 00005C88 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2283                              <1>        		; br 1f / branch if block already in a I/O buffer
  2284 00005C8A 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2285                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2286 00005C8F E8DA010000          <1> 	call	poke
  2287                              <1>         	; jsr r0,poke / perform the read
  2288                              <1> 	;;jc	error ;2 0/07/2013
  2289                              <1> ; 1:
  2290                              <1>  		; clr *$ps / ps = 0
  2291                              <1>         	; rts r0
  2292                              <1> 	; 08/02/2022
  2293 00005C94 7305                <1> 	jnc	short bread_2
  2294 00005C96 E937010000          <1> 	jmp	dskrd_err
  2295                              <1> 	;
  2296                              <1> ;; return from preread
  2297                              <1> bread_2:
  2298 00005C9B 66810B0040          <1> 	or	word [ebx], 4000h 
  2299                              <1> 		; bis $40000,(r5) 
  2300                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2301                              <1> bread_3: ; 1:
  2302 00005CA0 66F7030024          <1> 	test	word [ebx], 2400h
  2303                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2304 00005CA5 7407                <1> 	jz	short bread_4
  2305                              <1> 		; beq 1f / no
  2306                              <1> 		; cmp cdev,$1 / disk or drum?
  2307                              <1> 		; ble 2f / yes
  2308                              <1> 		; tstb uquant / is the time quantum = 0?
  2309                              <1> 		; bne 2f / no, 2f
  2310                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2311                              <1> 		; jsr r0,sleep; 31. 
  2312                              <1> 			; / put process to sleep in channel 31 (tape)
  2313                              <1> 		; mov (sp)+,r5 / restore r5
  2314                              <1> 		; br 1b / go back
  2315                              <1> ; 2: / drum or disk
  2316                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2317 00005CA7 E8C2F2FFFF          <1> 	call	idle
  2318                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2319 00005CAC EBF2                <1> 	jmp	short bread_3
  2320                              <1>        		; br 1b
  2321                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2322 00005CAE 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2323                              <1> 		; bic $40000,(r5) / clear bit 14
  2324                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2325 00005CB3 83C308              <1> 	add	ebx, 8
  2326                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2327                              <1> 	; 09/06/2015
  2328 00005CB6 66833D[B1700000]00  <1> 	cmp	word [u.pcount], 0
  2329 00005CBE 7705                <1> 	ja	short bread_5
  2330 00005CC0 E880F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2331                              <1> bread_5:
  2332                              <1> 	; eBX = system (I/O) buffer address
  2333 00005CC5 E870000000          <1> 	call	dioreg
  2334                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2335                              <1> 	; esi = start address of the transfer (in the buffer)
  2336                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2337                              <1> 	; ecx = transfer count (in bytes)
  2338                              <1> 	;
  2339                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2340                              <1> ;   / of users data
  2341 00005CCA F3A4                <1> 	rep	movsb
  2342                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2343                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2344                              <1>        		; bne 1b
  2345 00005CCC 59                  <1> 	pop	ecx ; **
  2346 00005CCD 833D[70700000]00    <1> 	cmp	dword [u.count], 0
  2347                              <1> 		; tst u.count / done
  2348 00005CD4 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2349                              <1>        		; beq 1f / yes, return
  2350                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2351                              <1>        		; br bread / read some more
  2352                              <1> ; 1:
  2353 00005CD6 58                  <1> 	pop	eax ; ****
  2354                              <1>        		; mov (sp)+,r0
  2355 00005CD7 C3                  <1>         retn		; 09/06/2015
  2356                              <1> 	;jmp	ret_ 
  2357                              <1> 		;jmp ret  / jump to routine that called readi
  2358                              <1> 
  2359                              <1> 	; 08/02/2022
  2360                              <1> brw_oov_err:
  2361 00005CD8 C705[A1700000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2361 00005CE0 0000                <1>
  2362 00005CE2 E9D8DDFFFF          <1> 	jmp	error
  2363                              <1> 
  2364                              <1> 	; 08/02/2022
  2365                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2366                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2367                              <1> 	; 26/04/2013
  2368                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2369                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2370                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2371                              <1> 
  2372                              <1> 
  2373                              <1> 	; 08/02/2022
  2374                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2375                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2376                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2377                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2378                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2379                              <1> 
  2380                              <1> bwrite:
  2381                              <1> 	; 08/02/2022
  2382                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2383                              <1> 	; 14/07/2015
  2384                              <1> 	; 10/07/2015
  2385                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2386                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2387                              <1> 	;	
  2388                              <1> 	;; / write on block structured device
  2389                              <1> 	;
  2390                              <1> 	; INPUTS ->
  2391                              <1> 	;    [u.fofp] points to the block number
  2392                              <1> 	;    CX = maximum block number allowed on device
  2393                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2394                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2395                              <1> 	;    [u.count]	number of bytes to user desires to write
  2396                              <1> 	; OUTPUTS ->
  2397                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2398                              <1> 	;
  2399                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2400                              <1> 	;
  2401                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2402                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2403                              <1> 	;	is increased by 1. For example: If user/program request 
  2404                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2405                              <1> 	;  	the next block number just as 512 byte writing is done.
  2406                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2407                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2408                              <1> 	;       enough to keep byte position/offset of the disk), this
  2409                              <1> 	;	defect will not be corrected, user/program must request
  2410                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2411                              <1> 	;       for achieving correct result. In future version(s), 
  2412                              <1> 	;	this defect will be corrected by using different 
  2413                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2414                              <1> 
  2415                              <1>        		; jsr r0,tstdeve / test the device for an error
  2416                              <1> 	;push	ecx ; **
  2417                              <1> 	; 26/04/2013
  2418                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2419 00005CE7 2C03                <1> 	sub	al, 3
  2420                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2421 00005CE9 A2[B4700000]        <1> 	mov	[u.brwdev], al
  2422                              <1> 	; 09/06/2015
  2423                              <1> 	;movzx	ebx, al
  2424                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2425                              <1> 	; 12/01/2022 (BugFix)
  2426 00005CEE C0E002              <1> 	shl	al, 2 ; * 4
  2427 00005CF1 8B88[AE670000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2428                              <1> bwrite_0:
  2429 00005CF7 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2430                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2431                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2432 00005CF8 8B1D[5C700000]      <1> 	mov	ebx, [u.fofp]
  2433 00005CFE 8B03                <1> 	mov	eax, [ebx]       
  2434 00005D00 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2435                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2436 00005D03 39C8                <1> 	cmp	eax, ecx
  2437                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2438                              <1>        	                     ; / block number allowed
  2439                              <1> 	;jnb	error	     ; 18/04/2013
  2440                              <1> 		; bhis error10 / yes, error
  2441                              <1>      	; 08/02/2022
  2442                              <1> 	;jb	short bwrite_1
  2443                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2444                              <1> 	;jmp	error
  2445 00005D05 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2446                              <1> bwrite_1:
  2447                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2448                              <1> 		; inc *u.fofp / no, increment block number
  2449                              <1> 	; 09/06/2015 - 10/07/2015
  2450 00005D07 66833D[B1700000]00  <1> 	cmp	word [u.pcount], 0
  2451 00005D0F 7705                <1> 	ja	short bwrite_2
  2452 00005D11 E82BF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2453                              <1> bwrite_2:
  2454 00005D16 BF[B4700000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2455 00005D1B E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2456                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2457                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2458 00005D20 E815000000          <1>         call	dioreg
  2459                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2460                              <1> 	; esi = destination address (in the buffer)
  2461                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2462                              <1> 	; ecx = transfer count (in bytes)
  2463                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2464 00005D25 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2465 00005D27 F3A4                <1> 	rep	movsb
  2466                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2467                              <1>        		; dec r3 / area to the I/O buffer
  2468                              <1>        		; bne 1b
  2469 00005D29 E80D010000          <1> 	call	dskwr
  2470                              <1> 		; jsr r0,dskwr / write it out on the device
  2471 00005D2E 59                  <1> 	pop	ecx ; **
  2472 00005D2F 833D[70700000]00    <1>         cmp     dword [u.count], 0
  2473                              <1> 		; tst u.count / done
  2474 00005D36 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2475                              <1> 		; beq 1f / yes, 1f
  2476                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2477                              <1>        		; br bwrite / go back and write next block
  2478                              <1> ; 1:
  2479 00005D38 58                  <1> 	pop	eax ; ****
  2480                              <1>        		; mov (sp)+,r0
  2481 00005D39 C3                  <1> 	retn		; 09/06/2015
  2482                              <1>         ;jmp	ret_ 
  2483                              <1> 		; jmp ret / return to routine that called writei
  2484                              <1> ;error10:
  2485                              <1> ;       jmp     error  ; / see 'error' routine
  2486                              <1> 
  2487                              <1> dioreg:
  2488                              <1> 	; 04/02/2022
  2489                              <1> 	; 14/07/2015
  2490                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2491                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2492                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2493                              <1> 	;	
  2494                              <1> 	; bookkeeping on block transfers of data
  2495                              <1> 	;
  2496                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2497                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2498                              <1> 	; 10/07/2015
  2499                              <1> 	; * returns byte offset from beginning of current sector buffer
  2500                              <1> 	; (beginning of data) in ESI
  2501                              <1> 	;
  2502 00005D3A 8B0D[70700000]      <1> 	mov	ecx, [u.count]
  2503                              <1> 		; mov u.count,r3 / move char count to r3
  2504                              <1> 	; 04/02/2022
  2505 00005D40 31D2                <1> 	xor	edx, edx
  2506 00005D42 B602                <1> 	mov	dh, 2
  2507                              <1> 	; edx = 512
  2508 00005D44 39D1                <1> 	cmp	ecx, edx ; 512
  2509                              <1> 	;cmp 	ecx, 512
  2510                              <1> 		; cmp r3,$512. / more than 512. char?
  2511 00005D46 7602                <1> 	jna	short dioreg_0
  2512                              <1> 		; blos 1f / no, branch
  2513 00005D48 89D1                <1> 	mov	ecx, edx ; 512
  2514                              <1> 	;mov	ecx, 512
  2515                              <1> 		; mov $512.,r3 / yes, just take 512.
  2516                              <1> dioreg_0:
  2517                              <1> 	; 09/06/2015
  2518 00005D4A 663B0D[B1700000]    <1> 	cmp	cx, [u.pcount]
  2519 00005D51 7607                <1> 	jna	short dioreg_1
  2520 00005D53 668B0D[B1700000]    <1> 	mov	cx, [u.pcount]
  2521                              <1> dioreg_1:
  2522                              <1> ; 1:
  2523 00005D5A 8B15[6C700000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2524                              <1> 	        ; mov u.base,r2 / put users base in r2
  2525 00005D60 010D[74700000]      <1> 	add	[u.nread], ecx
  2526                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2527 00005D66 290D[70700000]      <1> 	sub	[u.count], ecx
  2528                              <1> 		; sub r3,u.count / update count
  2529 00005D6C 010D[6C700000]      <1> 	add	[u.base], ecx
  2530                              <1> 		; add r3,u.base / update base
  2531                              <1> 	; 10/07/2015
  2532                              <1> 	; Retro UNIX 386 v1 - modification !
  2533                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2534                              <1> 	; (It will point to next byte position instead of next block no.)
  2535 00005D72 8B35[5C700000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2536 00005D78 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2537 00005D7A 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2538 00005D7C 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2539 00005D81 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2540 00005D83 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2541                              <1> 	; 09/06/2015 - 10/07/2015
  2542 00005D85 66290D[B1700000]    <1> 	sub	[u.pcount], cx
  2543 00005D8C 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2544 00005D92 8B3D[AD700000]      <1> 	mov	edi, [u.pbase]
  2545 00005D98 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2546 00005D9E 01D7                <1> 	add	edi, edx
  2547 00005DA0 893D[AD700000]      <1> 	mov	[u.pbase], edi
  2548 00005DA6 010D[AD700000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2549 00005DAC C3                  <1> 	retn
  2550                              <1> 		; rts r0 / return
  2551                              <1> 
  2552                              <1> dskrd:
  2553                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2554                              <1> 	; 18/08/2015
  2555                              <1> 	; 02/07/2015
  2556                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2557                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2558                              <1> 	;
  2559                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2560                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2561                              <1> 	; (number specified in r1) in the acquired buffer.)
  2562                              <1> 	; If the device is busy at the time dskrd is called,	
  2563                              <1> 	; dskrd calls idle.
  2564                              <1> 	; 
  2565                              <1> 	; INPUTS ->
  2566                              <1> 	;    r1 - block number
  2567                              <1> 	;    cdev - current device number 
  2568                              <1> 	; OUTPUTS ->
  2569                              <1> 	;    r5 - points to first data word in I/O buffer
  2570                              <1> 	;
  2571                              <1> 	; ((AX = R1)) input/output
  2572                              <1> 	; ((BX = R5)) output 
  2573                              <1> 	;
  2574                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2575                              <1> 	;
  2576 00005DAD E851010000          <1> 	call 	bufaloc
  2577                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2578                              <1> 			       ; / get a free I/O buffer
  2579                              <1> 	;;jc	error ; 20/07/2013
  2580 00005DB2 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2581                              <1>        		; br 1f / branch if block already in a I/O buffer
  2582                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2583 00005DB4 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2584                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2585                              <1> 		               ; / I/O queue entry for buffer
  2586 00005DB9 E8B0000000          <1> 	call	poke
  2587                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2588                              <1> 			    ; /	bit 10=1 says read
  2589                              <1> 	; 09/06/2015
  2590                              <1> 	;jnc	short dskrd_1
  2591                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2592                              <1> 	;jmp	error
  2593                              <1> 	; 08/02/2022
  2594 00005DBE 7212                <1> 	jc	short dskrd_3
  2595                              <1> dskrd_1: ; 1:
  2596                              <1>        		;clr *$ps
  2597 00005DC0 66F7030024          <1>        	test	word [ebx], 2400h
  2598                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2599                              <1> 				; / jump to idle
  2600 00005DC5 7407                <1>        	jz	short dskrd_2
  2601                              <1> 		; beq 1f
  2602                              <1>         ;;mov   ecx, [s.wait_]
  2603 00005DC7 E8A2F1FFFF          <1>        	call	idle
  2604                              <1> 		; jsr r0,idle; s.wait+2
  2605 00005DCC EBF2                <1> 	jmp 	short dskrd_1
  2606                              <1>        		; br 1b
  2607                              <1> dskrd_2: ; 1:
  2608 00005DCE 83C308              <1>         add	ebx, 8
  2609                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2610                              <1> 			  ; / just read in
  2611 00005DD1 C3                  <1>        	retn
  2612                              <1> 		; rts r0
  2613                              <1> dskrd_err: 
  2614                              <1> 	; 08/02/2022
  2615                              <1> 	; (jump from 'bread' error)	
  2616                              <1> dskrd_3:	
  2617                              <1> 	; 08/02/2022
  2618 00005DD2 803D[B4700000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2619 00005DD9 7509                <1> 	jne	short dskrd_4 ; no
  2620                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2621 00005DDB C605[B4700000]00    <1> 	mov	byte [u.brwdev], 0
  2622 00005DE2 EB0A                <1> 	jmp	short dskrd_5
  2623                              <1> dskrd_4:
  2624 00005DE4 C705[A1700000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2624 00005DEC 0000                <1>
  2625                              <1> dskrd_5:
  2626 00005DEE E9CCDCFFFF          <1> 	jmp	error
  2627                              <1> 
  2628                              <1> bwslot:
  2629                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2630                              <1> 	; 10/07/2015
  2631                              <1> 	;	If the block/sector is not placed in a buffer
  2632                              <1> 	;	before 'wslot', it must be read before
  2633                              <1> 	;	it is written! (Otherwise transfer counts less
  2634                              <1> 	;	than 512 bytes will be able to destroy existing 
  2635                              <1> 	;	data on disk.)
  2636                              <1> 	;
  2637                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2638                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2639                              <1> 	; Retro UNIX 8086 v1 modification !
  2640                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2641                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2642                              <1> 	;	-> eAX = block number
  2643                              <1> 	;
  2644 00005DF3 E818010000          <1> 	call	bufaloc_0
  2645 00005DF8 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2646                              <1> 	; 12/01/2022
  2647                              <1> 	; ebx = buffer header address
  2648                              <1> bwslot_0:
  2649                              <1> 	; 10/07/2015
  2650 00005DFA 8B35[5C700000]      <1> 	mov	esi, [u.fofp]
  2651 00005E00 8B06                <1> 	mov	eax, [esi]
  2652 00005E02 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2653 00005E07 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2654                              <1> 		       ; recent disk data must be placed in the buffer
  2655 00005E09 813D[70700000]0002- <1> 	cmp	dword [u.count], 512
  2655 00005E11 0000                <1>
  2656 00005E13 730F                <1> 	jnb	short wslot_0	
  2657                              <1> bwslot_1:
  2658 00005E15 E89AFFFFFF          <1> 	call	dskrd_0
  2659                              <1> 	; 12/01/2022
  2660                              <1> 	; ebx = buffer data address = buffer header address + 8
  2661 00005E1A 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2662 00005E1D EB05                <1> 	jmp 	short wslot_0
  2663                              <1> 
  2664                              <1> wslot:
  2665                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2666                              <1> 	; 		(32 bit modifications)
  2667                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2668                              <1> 	;
  2669                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2670                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2671                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2672                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2673                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2674                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2675                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2676                              <1> 	;
  2677                              <1> 	; INPUTS ->
  2678                              <1>  	;    r1 - block number
  2679                              <1> 	;    cdev - current (block/disk) device number
  2680                              <1>  	;
  2681                              <1> 	; OUTPUTS ->
  2682                              <1> 	;    bufp - bits 9 and 15 are set, 
  2683                              <1> 	;           the remainder of the word left unchanged
  2684                              <1> 	;    r5 - points to first data word in I/O buffer
  2685                              <1> 	;
  2686                              <1> 	; ((AX = R1)) input/output
  2687                              <1> 	; ((BX = R5)) output 
  2688                              <1> 	;
  2689                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2690                              <1> 
  2691 00005E1F E8DF000000          <1> 	call	bufaloc
  2692                              <1> 	; 10/07/2015
  2693                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2694                              <1>         	; br 1f / word in buffer in r5
  2695                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2696                              <1>         ; eAX = Block/Sector number (r1)
  2697                              <1> wslot_0: ;1:
  2698 00005E24 66F7030024          <1>      	test	word [ebx], 2400h
  2699                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2700                              <1> 				; / of I/O queue entry
  2701 00005E29 7407                <1> 	jz	short wslot_1
  2702                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2703                              <1> 		     ; / or not waiting to read)
  2704                              <1> 
  2705                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2706 00005E2B E83EF1FFFF          <1> 	call	idle
  2707                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2708                              <1>        	                     ; / idle
  2709 00005E30 EBF2                <1> 	jmp	short wslot_0
  2710                              <1> 		; br 1b / till finished
  2711                              <1> wslot_1: ;1:
  2712 00005E32 66810B0082          <1>         or      word [ebx], 8200h
  2713                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2714                              <1>                             	 ; / (write, inhibit bits)
  2715                              <1>        		; clr     *$ps / clear processor status
  2716 00005E37 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2717                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2718                              <1> 			  ; / for this block
  2719                              <1> dskwr_1:	; 08/02/2022
  2720 00005E3A C3                  <1>        	retn
  2721                              <1> 		; rts r0
  2722                              <1> dskwr:
  2723                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2724                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2725                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2726                              <1> 	;
  2727                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2728                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2729                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2730                              <1> 	; previously has supplied all the information required in the
  2731                              <1> 	; I/O queue entry.
  2732                              <1> 	;
  2733                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2734                              <1> 	;
  2735                              <1> 	;
  2736 00005E3B 8B1D[0C700000]      <1> 	mov	ebx, [bufp]
  2737 00005E41 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2738                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2739                              <1>                                   ; / bottom of queue
  2740 00005E46 E823000000          <1> 	call	poke
  2741                              <1> 	; 09/06/2015
  2742 00005E4B 73ED                <1> 	jnc	short dskwr_1
  2743                              <1> 	; 08/02/2022
  2744 00005E4D 803D[B4700000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2745 00005E54 7509                <1> 	jne	short dskwr_0 ; no
  2746                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2747 00005E56 C605[B4700000]00    <1> 	mov	byte [u.brwdev], 0
  2748 00005E5D EB0A                <1> 	jmp	short dskwr_2
  2749                              <1> dskwr_0:
  2750 00005E5F C705[A1700000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2750 00005E67 0000                <1>
  2751                              <1> dskwr_2:
  2752 00005E69 E951DCFFFF          <1> 	jmp	error
  2753                              <1> ;dskwr_1:
  2754                              <1> ;	retn
  2755                              <1> 
  2756                              <1> ;ppoke:
  2757                              <1>        		; mov $340,*$ps
  2758                              <1>        		; jsr r0,poke
  2759                              <1>        		; clr *$ps
  2760                              <1> 		; rts r0
  2761                              <1> poke:
  2762                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2763                              <1> 	; 24/10/2015
  2764                              <1> 	; 20/08/2015
  2765                              <1> 	; 18/08/2015
  2766                              <1> 	; 02/07/2015
  2767                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2768                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2769                              <1> 	;
  2770                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2771                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2772                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2773                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2774                              <1> 	;
  2775                              <1> 	; Basic I/O functions for all block structured devices
  2776                              <1> 	;
  2777                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2778                              <1> 	;
  2779                              <1> 	; 20/07/2013 modifications
  2780                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2781                              <1> 	; INPUTS -> 
  2782                              <1> 	;        (EBX = buffer header address)
  2783                              <1> 	; OUTPUTS ->
  2784                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2785                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2786                              <1> 	;		(drive not ready or r/w error!)
  2787                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2788                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2789                              <1> 	;        (also it indicates invalid buffer data)
  2790                              <1> 	;
  2791 00005E6E 53                  <1> 	push	ebx
  2792                              <1>        		; mov r1,-(sp)
  2793                              <1>        		; mov r2,-(sp)
  2794                              <1>        		; mov r3,-(sp)
  2795 00005E6F 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2796                              <1> 	;
  2797                              <1> 	; 09/06/2015
  2798                              <1> 	; (permit read/write after a disk  R/W error)
  2799 00005E70 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2800 00005E72 B001                <1> 	mov	al, 1
  2801 00005E74 D2E0                <1> 	shl	al, cl
  2802 00005E76 8405[32700000]      <1> 	test 	al, [active] ; busy ? (error)
  2803 00005E7C 7408                <1> 	jz	short poke_0
  2804 00005E7E F6D0                <1> 	not	al
  2805 00005E80 2005[32700000]      <1> 	and	[active], al ; reset busy bit for this device only
  2806                              <1> poke_0:
  2807 00005E86 BE[2C700000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2808                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2809                              <1> 					 ; / I/O queue pointer
  2810                              <1> poke_1: ; 1:
  2811 00005E8B 83EE04              <1>         sub	esi, 4
  2812 00005E8E 8B1E                <1> 	mov	ebx, [esi]
  2813                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2814 00005E90 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2815 00005E93 F6C406              <1>        	test	ah, 06h
  2816                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2817                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2818                              <1> 			       ; / queue entry
  2819 00005E96 745C                <1>         jz      short poke_5
  2820                              <1> 		; beq 2f / branch to 2f if both are clear
  2821                              <1> 	; 31/07/2013
  2822                              <1> 	;test	ah, 0B0h ; (*)
  2823                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2824                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2825                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2826                              <1> 		; bne 2f / branch if any are set
  2827                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2828                              <1>     		; movb (r1),r3 / get device id
  2829 00005E98 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2830                              <1> 	;mov	edi, ecx ; 26/04/2013
  2831 00005E9B 31C0                <1> 	xor 	eax, eax ; 0
  2832                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2833                              <1> 		; tstb deverr(r3) / test for errors on this device
  2834                              <1>        	;jna	short poke_2 
  2835                              <1> 		; beq 3f / branch if no errors
  2836                              <1> 	; 02/07/2015
  2837                              <1> 	;dec	eax
  2838                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2839                              <1>        		; mov $-1,2(r1) / destroy associativity
  2840                              <1> 	;shr	eax, 24
  2841                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2842                              <1> 		; clrb 1(r1) / do not do I/O
  2843                              <1> 	;jmp	short poke_5
  2844                              <1>         ;       ; br 2f
  2845                              <1>                 ; rts r0
  2846                              <1> poke_2: ; 3:
  2847                              <1> 	; 02/07/2015
  2848 00005E9D FEC1                <1> 	inc	cl ; 0FFh -> 0
  2849 00005E9F 7453                <1> 	jz	short poke_5
  2850 00005EA1 FEC0                <1> 	inc	al ; mov ax, 1
  2851 00005EA3 FEC9                <1> 	dec	cl
  2852 00005EA5 7402                <1> 	jz	short poke_3
  2853                              <1> 	; 26/04/2013 Modification
  2854                              <1> 	;inc	al ; mov ax, 1
  2855                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2856                              <1> 	;jz	short poke_3 ; cl = 0
  2857 00005EA7 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2858                              <1> poke_3:
  2859                              <1> 	;test	[active], ax
  2860 00005EA9 8405[32700000]      <1> 	test	[active], al
  2861                              <1> 		; bit $2,active / test disk busy bit
  2862 00005EAF 7543                <1> 	jnz     short poke_5
  2863                              <1> 		; bne 2f / branch if bit is set
  2864                              <1> 	;or	[active], ax
  2865 00005EB1 0805[32700000]      <1> 	or	[active], al
  2866                              <1> 		; bis $2,active / set disk busy bit
  2867                              <1> 	;push	ax
  2868                              <1> 	; 24/12/2021
  2869 00005EB7 50                  <1> 	push	eax
  2870 00005EB8 E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2871                              <1> 	;mov    [edi+drv.error], ah
  2872                              <1> 	; 24/12/2021
  2873 00005EBD 58                  <1> 	pop	eax
  2874                              <1> 	;pop	ax
  2875 00005EBE 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2876                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2877                              <1> 	;jna	short poke_4
  2878                              <1> 		; tstb deverr(r3) / test for errors on this device
  2879                              <1>        		; beq 3f / branch if no errors
  2880                              <1> 	; 02/07/2015 (32 bit modification)
  2881                              <1> 	; 20/07/2013
  2882 00005EC0 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2883                              <1>        		; mov $-1,2(r1) / destroy associativity
  2884 00005EC7 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2885                              <1> 		; clrb 1(r1) / do not do I/O
  2886 00005ECC EB26                <1> 	jmp     short poke_5
  2887                              <1> poke_4:	; 20/07/2013
  2888                              <1> 	; 17/07/2013
  2889 00005ECE F6D0                <1> 	not 	al 
  2890 00005ED0 2005[32700000]      <1> 	and	[active], al ; reset, not busy
  2891                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2892                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2893 00005ED6 668B03              <1> 	mov	ax, [ebx]
  2894                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2895 00005ED9 66250006            <1>         and	ax, 600h
  2896                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2897 00005EDD 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2898                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2899 00005EE2 C0E403              <1> 	shl	ah, 3
  2900                              <1>        		; rol r3
  2901                              <1>                 ; rol r3
  2902                              <1>                 ; rol r3	
  2903 00005EE5 660903              <1> 	or	[ebx], ax
  2904                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2905                              <1> 			   ; bits 12 and 13
  2906 00005EE8 E881F0FFFF          <1> 	call	idle ; 18/01/2014
  2907                              <1> 	;; sti
  2908                              <1> 	;hlt 	; wait for a hardware interrupt
  2909                              <1> 	;; cli
  2910                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2911                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2912                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2913                              <1> 	; method, this procedure will wait for a time according to
  2914                              <1> 	; multi tasking and time sharing concept.
  2915                              <1> 	;
  2916                              <1> 	; 24/10/2015
  2917                              <1> 	;not	ax 
  2918 00005EED 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2919 00005EF1 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2920                              <1> poke_5: ;2:
  2921 00005EF4 81FE[0C700000]      <1>         cmp     esi, bufp
  2922                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2923                              <1>                             ; / has been scanned
  2924 00005EFA 778F                <1> 	ja      short poke_1
  2925                              <1>                ; bhi 1b
  2926                              <1> 	; 24/03/2013
  2927                              <1>        		; mov (sp)+,r3
  2928                              <1>        		; mov (sp)+,r2
  2929                              <1>        		; mov (sp)+,r1
  2930 00005EFC 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2931 00005EFD 5B                  <1> 	pop 	ebx
  2932                              <1> 	; 02/07/2015 (32 bit modification)
  2933                              <1> 	; 20/07/2013
  2934                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2935 00005EFE 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2936                              <1> 	;	
  2937                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2938                              <1> 	; or written successfully; even if an error occurs while
  2939                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2940                              <1> 	;
  2941                              <1> 	; 09/06/2015
  2942 00005F01 F5                  <1> 	cmc
  2943 00005F02 C3                  <1> 	retn
  2944                              <1>                 ; rts r0
  2945                              <1> 
  2946                              <1> bufaloc:
  2947                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2948                              <1> 	; 20/08/2015
  2949                              <1> 	; 19/08/2015
  2950                              <1> 	; 02/07/2015
  2951                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2952                              <1> 	;	     (32 bit modifications)	
  2953                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2954                              <1> 	;
  2955                              <1> 	; bufaloc - Block device I/O buffer allocation
  2956                              <1> 	; 
  2957                              <1> 	; INPUTS ->
  2958                              <1> 	;    r1 - block number
  2959                              <1> 	;    cdev - current (block/disk) device number
  2960                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2961                              <1> 	; OUTPUTS ->
  2962                              <1> 	;    r5 - pointer to buffer allocated
  2963                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2964                              <1> 	;
  2965                              <1> 	; ((AX = R1)) input/output
  2966                              <1> 	; ((BX = R5)) output
  2967                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2968                              <1> 	;    zf=1 -> block already in a I/O buffer
  2969                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2970                              <1> 	;    ((DL = Device ID))
  2971                              <1> 	;    (((DH = 0 or 1)))
  2972                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2973                              <1> 	;    ((CX and DH will not be used after return)))
  2974                              <1> 
  2975                              <1> 	;;push 	esi ; ***
  2976                              <1> 		; mov r2,-(sp) / save r2 on stack
  2977                              <1>        		; mov $340,*$ps / set processor priority to 7
  2978                              <1> 	; 20/07/2013
  2979                              <1> 	; 26/04/2013
  2980                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2981                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  2982                              <1> 	;add	edi, ebx
  2983                              <1> 	; 09/01/2022
  2984 00005F03 0FB63D[2F700000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2985 00005F0A 81C7[30700000]      <1> 	add	edi, rdev
  2986                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2987                              <1> 			;; eDI points to device id.
  2988 00005F10 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2989                              <1> 	; 11/06/2015
  2990 00005F13 80BB[CA670000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2991 00005F1A 720F                <1> 	jb	short bufaloc_9
  2992 00005F1C C705[A1700000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2992 00005F24 0000                <1>
  2993 00005F26 E994DBFFFF          <1> 	jmp	error
  2994                              <1> bufaloc_9:
  2995 00005F2B 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2996                              <1> bufaloc_10: ; 02/07/2015
  2997 00005F2D 31ED                <1> 	xor 	ebp, ebp ; 0
  2998 00005F2F 55                  <1> 	push	ebp ; 0
  2999 00005F30 89E5                <1>         mov     ebp, esp	
  3000                              <1> 	;
  3001                              <1> bufaloc_1: ;1:
  3002                              <1> 		; clr -(sp) / vacant buffer
  3003 00005F32 BE[0C700000]        <1>         mov 	esi, bufp
  3004                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3005                              <1> 			     ; / entrys in buffer area
  3006                              <1> bufaloc_2: ;2:
  3007 00005F37 8B1E                <1> 	mov	ebx, [esi]
  3008                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3009                              <1> 			    ; queue entry into r5
  3010 00005F39 66F70300F6          <1> 	test	word [ebx], 0F600h
  3011                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3012 00005F3E 7503                <1>         jnz	short bufaloc_3
  3013                              <1> 		; bne 3f / branch when 
  3014                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3015                              <1>                        ; / (i.e., buffer busy)
  3016 00005F40 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3017                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3018                              <1> 			; / found points to word 2 of I/O queue entry)
  3019                              <1> bufaloc_3: ;3:
  3020                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3021                              <1> 	;
  3022 00005F43 3813                <1> 	cmp	[ebx], dl	
  3023                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3024                              <1> 			       ; / as current device
  3025 00005F45 7508                <1> 	jne	short bufaloc_4
  3026                              <1>        		; bne 3f
  3027 00005F47 394304              <1> 	cmp	[ebx+4], eax
  3028                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3029                              <1> 			     ; / same as current block number
  3030 00005F4A 7503                <1>        	jne	short bufaloc_4
  3031                              <1> 		; bne 3f
  3032                              <1> 	;add	esp, 4
  3033 00005F4C 59                  <1> 	pop	ecx
  3034                              <1>        		; tst (sp)+ / bump stack pointer
  3035 00005F4D EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3036                              <1> 				; jump to bufaloc_6 in original Unix v1
  3037                              <1>        		; br 1f / use this buffer
  3038                              <1> bufaloc_4: ;3:
  3039 00005F4F 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3040                              <1> 	;
  3041 00005F52 81FE[24700000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3042                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3043 00005F58 72DD                <1> 	jb	short bufaloc_2
  3044                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3045                              <1>                        ; / buffers not checked)
  3046 00005F5A 5E                  <1>         pop	esi
  3047                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3048                              <1> 			     ; / to last free block
  3049 00005F5B 09F6                <1>        	or	esi, esi 
  3050 00005F5D 7507                <1> 	jnz	short bufaloc_5
  3051                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3052                              <1> 	        ; / if a free buffer is found branch to 2f
  3053                              <1>         ;; mov  ecx, [s.wait_]
  3054 00005F5F E80AF0FFFF          <1> 	call	idle
  3055                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3056 00005F64 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3057                              <1>        		; br 1b
  3058                              <1> bufaloc_5: ;2:
  3059                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3060 00005F66 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3061                              <1> bufaloc_6: ;1:
  3062 00005F68 8B1E                <1>         mov    	ebx, [esi] 
  3063                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3064                              <1> 			     ; / entry in r5
  3065                              <1> 	;; 26/04/2013
  3066                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3067 00005F6A 8813                <1> 	mov 	[ebx], dl
  3068                              <1> 		; movb cdev,(r5) / put current device number 
  3069                              <1> 				 ; / in I/O queue entry
  3070 00005F6C 894304              <1> 	mov 	[ebx+4], eax
  3071                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3072                              <1> 			     ; / of I/O queue entry
  3073                              <1> bufaloc_7: ;1:
  3074 00005F6F 81FE[0C700000]      <1>         cmp	esi, bufp
  3075                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3076                              <1> 			     ; / and put latest assigned
  3077 00005F75 760A                <1> 	jna	short bufaloc_8	
  3078                              <1>        		; blos 1f / buffer on the top 
  3079                              <1> 			; / (this makes if the lowest priority)
  3080 00005F77 83EE04              <1> 	sub	esi, 4
  3081 00005F7A 8B0E                <1> 	mov	ecx, [esi]
  3082 00005F7C 894E04              <1> 	mov	[esi+4], ecx
  3083                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3084 00005F7F EBEE                <1> 	jmp 	short bufaloc_7        
  3085                              <1> 		; br 1b
  3086                              <1> bufaloc_8: ;1:
  3087 00005F81 891E                <1>         mov	[esi], ebx
  3088                              <1> 		; mov r5,(r2)
  3089                              <1> 	;;pop	esi ; ***
  3090                              <1>        		; mov (sp)+,r2 / restore r2
  3091 00005F83 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3092                              <1> 		; Retro UNIX 8086 v1 modification
  3093                              <1> 		; zf=1 --> block already is in an I/O buffer
  3094                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3095 00005F85 C3                  <1> 	retn
  3096                              <1> 		; rts r0
  3097                              <1> 
  3098                              <1> diskio:
  3099                              <1> 	; 12/02/2022
  3100                              <1> 	; 10/02/2022
  3101                              <1> 	; 08/02/2022
  3102                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3103                              <1> 	; 10/07/2015
  3104                              <1> 	; 02/07/2015
  3105                              <1> 	; 16/06/2015
  3106                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3107                              <1> 	;	     (80386 protected mode modifications)	
  3108                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3109                              <1> 	;
  3110                              <1> 	; Retro UNIX 8086 v1 feature only !
  3111                              <1> 	;
  3112                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3113                              <1> 	; 04/07/2009 - 20/07/2011
  3114                              <1> 	;
  3115                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3116                              <1> 	;
  3117                              <1>         ; INPUTS ->
  3118                              <1> 	; 	   eBX = System I/O Buffer header address
  3119                              <1> 	;
  3120                              <1>         ; OUTPUTS -> cf=0 --> done 
  3121                              <1> 	; 	     cf=1 --> error code in AH
  3122                              <1> 	;	     ; 08/02/2022
  3123                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3124                              <1> 	;		error code in [u.error]
  3125                              <1> 	;		
  3126                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3127                              <1> 	
  3128                              <1> ;rw_disk_sector:
  3129                              <1> 	; 12/02/2022
  3130                              <1> 	; 10/02/2022
  3131                              <1> 	; 08/02/2022
  3132                              <1> 	; 10/07/2015
  3133                              <1> 	; 02/07/2015
  3134                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3135                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3136                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3137                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3138                              <1> 	;
  3139                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3140 00005F86 B602                <1> 	mov	dh, 2
  3141 00005F88 668B03              <1> 	mov	ax, [ebx] 
  3142                              <1> 	;
  3143 00005F8B 56                  <1> 	push	esi ; ****
  3144 00005F8C 53                  <1> 	push	ebx ; ***
  3145                              <1> 	;
  3146 00005F8D 0FB6C8              <1> 	movzx	ecx, al
  3147 00005F90 89CE                <1> 	mov	esi, ecx
  3148                              <1> 	;
  3149 00005F92 38F1                <1> 	cmp	cl, dh ; 2
  3150 00005F94 7202                <1> 	jb	short rwdsk0
  3151 00005F96 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3152                              <1> rwdsk0:
  3153 00005F98 A2[7B670000]        <1> 	mov	[drv], al
  3154 00005F9D 81C6[CA670000]      <1> 	add	esi, drv.status
  3155                              <1> 	; 11/06/2015
  3156 00005FA3 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3157 00005FA6 7204                <1> 	jb      short rwdsk1
  3158                              <1> 	; 'drive not ready' error
  3159                              <1> 	; 10/02/2022
  3160                              <1> 	; 08/02/2022
  3161                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3162                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3163                              <1> 	;;jmp	error
  3164                              <1> 	;stc	; cf = 1
  3165                              <1> 	;retn
  3166                              <1> 	; 10/02/2022
  3167 00005FA8 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3168 00005FAA EB20                <1> 	jmp	short rwdsk_err1
  3169                              <1> rwdsk1:
  3170 00005FAC F6C402              <1> 	test	ah, 2
  3171                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3172                              <1> 			 ; write bit
  3173 00005FAF 7402                <1> 	jz	short rwdsk2
  3174                              <1> 	;test	ah, 4
  3175                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3176                              <1> 	;		 ; read bit
  3177                              <1> 	;jz	short diskio_ret
  3178 00005FB1 FEC6                <1> 	inc	dh ; 03h = write
  3179                              <1> rwdsk2:
  3180 00005FB3 88C2                <1> 	mov	dl, al
  3181 00005FB5 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3182 00005FB8 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3183 00005FBA C0E102              <1> 	shl	cl, 2
  3184 00005FBD 81C1[AE670000]      <1> 	add	ecx, drv.size ; disk size
  3185 00005FC3 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3186 00005FC5 7214                <1> 	jb      short rwdsk3
  3187                              <1>  	; 'out of volume' error
  3188                              <1> 	; 10/02/2022
  3189                              <1> 	; 08/02/2022
  3190                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3191                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3192                              <1> 	;;jmp	error
  3193                              <1> 	;stc	; cf = 1
  3194                              <1> 	;retn
  3195                              <1> 	; 10/02/2022
  3196 00005FC7 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3197                              <1> rwdsk_err1:
  3198 00005FCC C605[B4700000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3199 00005FD3 890D[A1700000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3200 00005FD9 EB30                <1> 	jmp	short rwdsk_err2
  3201                              <1> rwdsk3:
  3202                              <1> 	; 11/06/2015
  3203 00005FDB 83C304              <1> 	add	ebx, 4 ; buffer address
  3204 00005FDE C605[D2700000]04    <1> 	mov	byte [retry_count], 4
  3205 00005FE5 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3206 00005FE8 7432                <1>         jz      short rwdsk_chs
  3207                              <1> rwdsk_lba:
  3208                              <1> 	; LBA read/write (with private LBA function) 
  3209                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3210 00005FEA 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3211 00005FED 89C1                <1> 	mov	ecx, eax ; sector number
  3212                              <1> 	; ebx = buffer (data) address
  3213                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3214                              <1> rwdsk_lba_retry:
  3215                              <1> 	;mov	dl, [drv]
  3216                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3217 00005FEF B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3218 00005FF1 00F4                <1> 	add	ah, dh		
  3219 00005FF3 B001                <1> 	mov	al, 1
  3220                              <1> 	;int	13h
  3221 00005FF5 E899C5FFFF          <1> 	call	int13h
  3222 00005FFA 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3223 00005FFC 730E                <1> 	jnc	short rwdsk_lba_ok
  3224 00005FFE 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3225 00006001 7408                <1>         je      short rwdsk_lba_fails
  3226 00006003 FE0D[D2700000]      <1> 	dec	byte [retry_count]
  3227 00006009 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3228                              <1> rwdsk_err2:	; 10/02/2022
  3229                              <1> rwdsk_lba_fails:
  3230 0000600B F9                  <1> 	stc
  3231                              <1> rwdsk_lba_ok:
  3232 0000600C 5B                  <1> 	pop	ebx ; ***
  3233 0000600D 5E                  <1> 	pop	esi ; ****
  3234 0000600E C3                  <1> 	retn
  3235                              <1> rwdsk_lba_reset:
  3236 0000600F B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3237                              <1> 	;int	13h
  3238 00006011 E87DC5FFFF          <1>         call	int13h
  3239 00006016 73D7                <1> 	jnc     short rwdsk_lba_retry
  3240 00006018 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3241 0000601A EBF0                <1> 	jmp	short rwdsk_lba_ok
  3242                              <1> 	;
  3243                              <1> 	; CHS read (convert LBA address to CHS values)	
  3244                              <1> rwdsk_chs:
  3245                              <1> 	; 10/07/2015
  3246 0000601C 81EE[CA670000]      <1> 	sub	esi, drv.status
  3247 00006022 89F1                <1> 	mov	ecx, esi
  3248 00006024 81C6[D1670000]      <1> 	add 	esi, drv.error
  3249                              <1> 	; 02/07/2015
  3250                              <1> 	; 16/06/2015
  3251                              <1>  	; 11/06/2015 
  3252 0000602A 53                  <1> 	push	ebx ; ** ; buffer
  3253 0000602B D1E1                <1> 	shl	ecx, 1
  3254 0000602D 51                  <1> 	push	ecx ; * 
  3255                              <1> 	;
  3256 0000602E 89CB                <1> 	mov	ebx, ecx
  3257 00006030 8835[D1700000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3258 00006036 31D2                <1> 	xor	edx, edx ; 0
  3259                              <1> 	; 09/01/2022
  3260                              <1> 	;sub	ecx, ecx 
  3261 00006038 81C3[A0670000]      <1>         add     ebx, drv.spt
  3262 0000603E 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3263                              <1> 		; EDX:EAX = LBA
  3264 00006041 F7F1                <1> 	div	ecx
  3265 00006043 88D1                <1> 	mov	cl, dl	; sector number - 1
  3266 00006045 FEC1                <1> 	inc	cl	; sector number (1 based)
  3267 00006047 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3268                              <1> 	;push	cx
  3269                              <1>         ; 09/01/2022
  3270 00006048 51                  <1> 	push	ecx
  3271 00006049 81C3[92670000]      <1> 	add     ebx, drv.heads
  3272 0000604F 668B0B              <1> 	mov	cx, [ebx] ; heads
  3273 00006052 31D2                <1> 	xor	edx, edx
  3274                              <1> 		; EAX = cylinders * heads + head
  3275 00006054 F7F1                <1> 	div	ecx
  3276                              <1> 	;pop	cx     ; sector number
  3277                              <1> 	; 09/01/2022
  3278 00006056 59                  <1> 	pop	ecx
  3279 00006057 88D6                <1> 	mov	dh, dl ; head number
  3280 00006059 8A15[7B670000]      <1> 	mov	dl, [drv]
  3281 0000605F 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3282 00006061 C0E406              <1> 	shl	ah, 6
  3283 00006064 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3284                              <1> 		       ; sector (bits 0-7)
  3285 00006066 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3286                              <1> 		; CL = sector (bits 0-5)
  3287                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3288                              <1> 		; CH = cylinder (bits 0-7)
  3289                              <1> 		; DH = head
  3290                              <1> 		; DL = drive
  3291                              <1> 	;
  3292 00006067 C605[D2700000]04    <1> 	mov	byte [retry_count], 4
  3293                              <1> rwdsk_retry:	
  3294 0000606E 8A25[D1700000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3295 00006074 B001                <1> 	mov	al, 1 ; sector count	
  3296                              <1> 	;int	13h
  3297 00006076 E818C5FFFF          <1> 	call	int13h
  3298 0000607B 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3299 0000607D 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3300 0000607F 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3301 00006082 7408                <1> 	je	short rwdsk_fails
  3302 00006084 FE0D[D2700000]      <1> 	dec	byte [retry_count]
  3303 0000608A 7504                <1> 	jnz	short rwdsk_reset
  3304                              <1> rwdsk_fails:
  3305 0000608C F9                  <1> 	stc
  3306                              <1> rwdsk_ok:
  3307 0000608D 5B                  <1> 	pop	ebx ; ***
  3308 0000608E 5E                  <1> 	pop	esi ; ****
  3309 0000608F C3                  <1> 	retn
  3310                              <1> rwdsk_reset:
  3311                              <1> 	; 02/02/2015
  3312 00006090 28E4                <1> 	sub	ah, ah
  3313 00006092 80FA80              <1> 	cmp	dl, 80h
  3314 00006095 7202                <1> 	jb	short rwdsk_fd_reset
  3315 00006097 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3316                              <1> rwdsk_fd_reset:
  3317                              <1> 	;int	13h
  3318 00006099 E8F5C4FFFF          <1>         call	int13h
  3319 0000609E 73CE                <1> 	jnc	short rwdsk_retry
  3320 000060A0 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3321 000060A2 EBE9                <1> 	jmp 	short rwdsk_ok
  3322                              <1> 
  3323                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3324                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3325                              <1> ;
  3326                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3327                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3328                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3329                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3330                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3331                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3332                              <1> ; as in original unix v1.
  3333                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3334                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3335                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3336                              <1> ;
  3337                              <1> ; Erdogan tan (10/07/2015) 
  3338                              <1> 
  3339                              <1> ;drum: / interrupt handler
  3340                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3341                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3342                              <1> ;                                      / error
  3343                              <1> ;               br 3f / no, error
  3344                              <1> ;       br      2f / error
  3345                              <1> ;
  3346                              <1> ;disk:
  3347                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3348                              <1> ;       jmp     *$0f
  3349                              <1> ;0:
  3350                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3351                              <1> ;      	        br 3f / no, errors
  3352                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3353                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3354                              <1> ;                        / to 1f
  3355                              <1> ;       br      4f
  3356                              <1> ;1:
  3357                              <1> ;       bit     $20000,rkcs
  3358                              <1> ;       beq     4f / wait for seek complete
  3359                              <1> ;       mov     $0b,0b-2
  3360                              <1> ;       mov     rkap,r1
  3361                              <1> ;2:
  3362                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3363                              <1> ;                          / the disk buffer
  3364                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3365                              <1> ;       inc     r1
  3366                              <1> ;       asr     (r1)
  3367                              <1> ;       asr     (r1)
  3368                              <1> ;       asr     (r1) / reissue request
  3369                              <1> ;       dec     r1
  3370                              <1> ;3:
  3371                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3372                              <1> ;       mov     ac,-(sp)
  3373                              <1> ;       mov     mq,-(sp) / put these on the stack
  3374                              <1> ;       mov     sc,-(sp)
  3375                              <1> ;       jsr     r0,poke
  3376                              <1> ;       mov     (sp)+,sc
  3377                              <1> ;       mov     (sp)+,mq / pop them off stack
  3378                              <1> ;       mov     (sp)+,ac
  3379                              <1> ;4:
  3380                              <1> ;       jmp     retisp / u4-3
  3381                              <1> ;
  3382                              <1> ;trapt:                  / r2 points to the
  3383                              <1> ;       mov     (r0)+,r2 / device control register
  3384                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3385                              <1> ;       tst     (sp)+
  3386                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3387                              <1> ;       bge     4b / device still active so branch
  3388                              <1> ;       bit     (r0),active / was device busy?
  3389                              <1> ;       beq     4b / no, stray interrupt
  3390                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3391                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3392                              <1> ;       bge     2f / if no error jump to 2f
  3393                              <1> ;       tst     (r0)+ / skip on error
  3394                              <1> ; 2:
  3395                              <1> ;       jmp     (r0)
  2110                                  %include 'u9.s'        ; 29/06/2015
  2111                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS9.INC
  2112                              <1> ; Last Modification: 13/06/2022
  2113                              <1> ; ----------------------------------------------------------------------------
  2114                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2115                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2116                              <1> ;
  2117                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2118                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2119                              <1> ; <Bell Laboratories (17/3/1972)>
  2120                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2121                              <1> ;
  2122                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2123                              <1> ;
  2124                              <1> ; ****************************************************************************
  2125                              <1> 
  2126                              <1> getch:
  2127                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2128                              <1> 	; 30/06/2015
  2129                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2130 000060A4 28C0                <1> 	sub	al, al ; 0
  2131                              <1> getch_q: ; 06/08/2015
  2132 000060A6 8A25[B66C0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2133 000060AC EB06                <1>         jmp     short getc_n
  2134                              <1> 
  2135                              <1> getc: 
  2136                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2137                              <1> 	; 12/11/2015
  2138                              <1> 	; 15/09/2015
  2139                              <1> 	; 01/07/2015
  2140                              <1> 	; 30/06/2015
  2141                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2142                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2143                              <1> 	;
  2144                              <1> 	; Retro UNIX 8086 v1 modification !
  2145                              <1> 	; 
  2146                              <1> 	; 'getc' gets (next) character 
  2147                              <1> 	;	 from requested TTY (keyboard) buffer 
  2148                              <1> 	; INPUTS ->
  2149                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2150                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2151                              <1> 	;	(Keyboard buffer will point to 
  2152                              <1> 	;			next character at next call)
  2153                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2154                              <1> 	;	(Keyboard buffer will point to 
  2155                              <1> 	;			current character at next call)
  2156                              <1> 	; OUTPUTS ->
  2157                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2158                              <1> 	;     			 ZF=0 -> AX has (current) character
  2159                              <1> 	;      AL = ascii code
  2160                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2161                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2162                              <1> 	; Original UNIX V1 'getc': 
  2163                              <1> 	;		get a character off character list
  2164                              <1> 	;
  2165                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2166                              <1> 	;
  2167                              <1> 	; 30/06/2015 (32 bit modifications)
  2168                              <1> 	; 16/07/2013
  2169                              <1> 	; mov 	[getctty], ah
  2170                              <1> 	;
  2171                              <1> 
  2172 000060AE 8A25[A0700000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2173                              <1> getc_n:
  2174                              <1> 	; 30/06/2015
  2175 000060B4 08E4                <1> 	or	ah, ah
  2176 000060B6 740D                <1> 	jz	short getc0 
  2177 000060B8 D0E4                <1> 	shl	ah, 1
  2178 000060BA 0FB6DC              <1> 	movzx	ebx, ah
  2179 000060BD 81C3[B86C0000]      <1> 	add	ebx, ttychr
  2180 000060C3 EB05                <1> 	jmp	short getc1
  2181                              <1> getc0:
  2182 000060C5 BB[B86C0000]        <1> 	mov	ebx, ttychr
  2183                              <1> getc1:
  2184 000060CA 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2185                              <1> 				; (by kb_int)	
  2186 000060CD 6609C9              <1> 	or	cx, cx
  2187 000060D0 7507                <1> 	jnz	short getc2
  2188 000060D2 20C0                <1> 	and 	al, al
  2189 000060D4 7415                <1> 	jz	short getc_s
  2190                              <1> 	;xor	ax, ax
  2191                              <1> 	; 24/12/2021
  2192 000060D6 31C0                <1> 	xor	eax, eax
  2193 000060D8 C3                  <1> 	retn
  2194                              <1> getc2:	
  2195 000060D9 20C0                <1> 	and	al, al
  2196 000060DB 6689C8              <1> 	mov	ax, cx
  2197 000060DE 66B90000            <1> 	mov	cx, 0
  2198 000060E2 7506                <1> 	jnz	short getc3
  2199                              <1> getc_sn:
  2200 000060E4 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2201 000060E7 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2202                              <1> getc3:
  2203 000060EA C3                  <1> 	retn
  2204                              <1> getc_s:
  2205                              <1> 	; 12/11/2015
  2206                              <1> 	; 15/09/2015
  2207                              <1> 	; 01/07/2015
  2208                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2209                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2210                              <1> 	;
  2211                              <1> 	; tty  of the current process is not 
  2212                              <1> 	; current tty (ptty); so, current process only 
  2213                              <1> 	; can use keyboard input when its tty becomes 
  2214                              <1> 	; current tty (ptty).
  2215                              <1> 	; 'sleep' is for preventing an endless lock
  2216                              <1> 	; during this tty input request.
  2217                              <1> 	; (Because, the user is not looking at the video page
  2218                              <1> 	; of the process to undersand there is a keyboard
  2219                              <1> 	; input request.)
  2220                              <1> 	;
  2221                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2222                              <1> 	;
  2223                              <1> 	; 05/10/2013
  2224                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2225                              <1> 	;
  2226                              <1> 	; 10/10/2013
  2227                              <1> gcw0:
  2228 000060EB B10A                <1> 	mov	cl, 10 ; ch = 0
  2229                              <1> gcw1:	
  2230                              <1> 	; 12/11/2015
  2231 000060ED E8DADAFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2232                              <1> 	; 10/10/2013
  2233 000060F2 E877EEFFFF          <1> 	call	idle
  2234 000060F7 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2235                              <1> 				; (by kb_int)
  2236 000060FA 6609C0              <1> 	or	ax, ax
  2237                              <1> ;	jnz	short gcw3
  2238 000060FD 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2239                              <1> 	; 30/06/2015
  2240 000060FF FEC9                <1> 	dec	cl
  2241 00006101 75EA                <1> 	jnz	short gcw1
  2242                              <1> 	;
  2243 00006103 8A25[A0700000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2244                              <1> ;	; 10/12/2013
  2245                              <1> ;	cmp 	ah, [ptty]
  2246                              <1> ;	jne	short gcw2
  2247                              <1> ;	; 14/02/2014
  2248                              <1> ;	cmp	byte [u.uno], 1
  2249                              <1> ;	jna	short gcw0		
  2250                              <1> ;gcw2:
  2251 00006109 E8EDEEFFFF          <1> 	call	sleep
  2252                              <1> 	;
  2253                              <1> 	; 20/09/2013
  2254 0000610E 8A25[A0700000]      <1> 	mov	ah, [u.ttyn]
  2255 00006114 30C0                <1> 	xor 	al, al
  2256 00006116 EB9C                <1> 	jmp	short getc_n
  2257                              <1> ;gcw3:
  2258                              <1> gcw2: 	; 15/09/2015
  2259                              <1> 	; 10/10/2013
  2260 00006118 30C9                <1> 	xor	cl, cl
  2261 0000611A EBC8                <1> 	jmp	short getc_sn
  2262                              <1> 
  2263                              <1> putc:	
  2264                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2265                              <1> 	; 13/08/2015
  2266                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2267                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2268                              <1> 	;
  2269                              <1> 	; Retro UNIX 8086 v1 modification !
  2270                              <1> 	; 
  2271                              <1> 	; 'putc' puts a character 
  2272                              <1> 	;	 onto requested (tty) video page or
  2273                              <1> 	;	 serial port
  2274                              <1> 	; INPUTS ->
  2275                              <1> 	;     AL = ascii code of the character
  2276                              <1> 	;     AH = video page (tty) number (0 to 7)
  2277                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2278                              <1> 	; OUTPUTS ->
  2279                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2280                              <1> 	;      			ZF=0 -> AX has (current) character
  2281                              <1> 	;     cf=0 and AH = 0 -> no error
  2282                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2283                              <1> 	; 
  2284                              <1> 	; Original UNIX V1 'putc': 
  2285                              <1> 	;     put a character at the end of character list
  2286                              <1> 	;
  2287                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2288                              <1> 	;
  2289 0000611C 80FC07              <1> 	cmp	ah, 7
  2290                              <1>         ;ja	sndc
  2291 0000611F 770A                <1>         ja      short sndc ; 24/12/2024
  2292                              <1> 	; 30/06/2015
  2293 00006121 0FB6DC              <1> 	movzx	ebx, ah
  2294                              <1> 	; 13/08/2015
  2295 00006124 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2296 00006126 E996B2FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2297                              <1> 
  2298                              <1> sndc:   ; <Send character>
  2299                              <1> 	;
  2300                              <1> 	; 12/01/2022
  2301                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2302                              <1> 	; 17/11/2015
  2303                              <1> 	; 16/11/2015
  2304                              <1> 	; 11/11/2015
  2305                              <1> 	; 10/11/2015
  2306                              <1> 	; 09/11/2015
  2307                              <1> 	; 08/11/2015
  2308                              <1> 	; 07/11/2015
  2309                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2310                              <1> 	; 29/10/2015
  2311                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2312                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2313                              <1> 	;
  2314                              <1> 	; Retro UNIX 8086 v1 feature only !
  2315                              <1> 	;
  2316                              <1> 	; ah = [u.ttyn]
  2317                              <1> 	;
  2318                              <1> 	; 30/06/2015
  2319 0000612B 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2320                              <1> 	; 07/11/2015
  2321 0000612E 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2322                              <1> sndc0:
  2323                              <1> 	; 07/11/2015
  2324 00006131 E813EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2325 00006136 7405                <1> 	jz	short sndc1
  2326 00006138 E88FDAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2327                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2328                              <1> sndc1:
  2329                              <1> 	; 16/11/2015
  2330                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2331                              <1> 	; 24/12/2021
  2332 0000613D 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2333                              <1> sndcx:
  2334 0000613F 8A83[FA6C0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2335 00006145 8AA3[F86C0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2336                              <1> 	;
  2337                              <1> 	; 17/11/2015
  2338                              <1> 	; check 'request for response' status
  2339 0000614B 80BB[F46C0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2340 00006152 740A                <1> 	jz	short query
  2341                              <1> response:
  2342 00006154 FE05[F76C0000]      <1> 	inc 	byte [comqr] ; query or response status
  2343 0000615A B0FF                <1> 	mov	al, 0FFh	 
  2344 0000615C EB14                <1> 	jmp	short sndc3
  2345                              <1> query:
  2346 0000615E 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2347 00006160 750E                <1> 	jnz 	short sndc2 ; normal character
  2348                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2349                              <1> 	;je	short sndc2  ; yes, already responded
  2350                              <1> 	; 16/11/2015
  2351                              <1> 	; query: request for response (again)
  2352 00006162 8883[F86C0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2353 00006168 FE05[F76C0000]      <1> 	inc 	byte [comqr] ; query or response status
  2354 0000616E EB02                <1> 	jmp	short sndc3
  2355                              <1> sndc2:
  2356 00006170 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2357                              <1> sndc3:
  2358 00006172 8883[FA6C0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2359 00006178 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2360                              <1> 	; 30/06/2015
  2361 0000617A E8F3D3FFFF          <1> 	call	sp_status ; get serial port status
  2362                              <1> 	; AL = Line status, AH = Modem status
  2363                              <1> 	; 07/11/2015
  2364 0000617F A880                <1> 	test	al, 80h
  2365 00006181 7504                <1> 	jnz	short sndc4
  2366 00006183 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2367 00006185 751A                <1> 	jnz	short sndc5
  2368                              <1> sndc4: 	; Check line status again
  2369                              <1> 	; 16/11/2015
  2370                              <1> 	;push	cx
  2371                              <1> 	; 24/12/2021
  2372 00006187 51                  <1> 	push	ecx
  2373                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2374                              <1> 	; 12/01/2022
  2375 00006188 31C9                <1> 	xor	ecx, ecx
  2376 0000618A B106                <1> 	mov	cl, 6
  2377 0000618C E827B3FFFF          <1> 	call	WAITF
  2378                              <1> 	;pop	cx
  2379                              <1> 	; 24/12/1021
  2380 00006191 59                  <1> 	pop	ecx
  2381                              <1> 	;
  2382 00006192 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2383 00006194 E8D9D3FFFF          <1> 	call	sp_status ; get serial port status
  2384                              <1> 	; 16/11/2015
  2385                              <1> 	; 09/11/2015
  2386                              <1> 	; 08/11/2015
  2387 00006199 A880                <1> 	test	al, 80h	; time out error
  2388 0000619B 7565                <1>         jnz     short sndc7
  2389 0000619D A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2390 0000619F 7461                <1>         jz	short sndc7
  2391                              <1> sndc5:  
  2392 000061A1 8A83[FA6C0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2393 000061A7 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2394 000061AB 28DE                <1> 	sub	dh, bl
  2395 000061AD EE                  <1> 	out	dx, al	   ; send on serial port
  2396                              <1> 	; 10/11/2015
  2397                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2398                              <1> 	; (to improve text flow to the terminal)
  2399                              <1> 	; ('diskette.inc': 'WAITF')
  2400                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2401                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2402                              <1> 	;push	cx
  2403                              <1> 	; 24/12/2021
  2404 000061AE 51                  <1> 	push	ecx
  2405                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2406                              <1> 	; 12/01/2022
  2407 000061AF 29C9                <1> 	sub	ecx, ecx
  2408 000061B1 B106                <1> 	mov	cl, 6
  2409 000061B3 E800B3FFFF          <1> 	call	WAITF
  2410                              <1> 	;pop	cx
  2411                              <1> 	; 24/12/1021
  2412 000061B8 59                  <1> 	pop	ecx
  2413                              <1>     	;
  2414                              <1> 	; 07/11/2015
  2415 000061B9 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2416                              <1> 	;
  2417 000061BB E8B2D3FFFF          <1> 	call	sp_status ; get serial port status
  2418                              <1> 	; AL = Line status, AH = Modem status
  2419                              <1> 	;
  2420 000061C0 E884EEFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2421 000061C5 7405                <1> 	jz	short sndc6
  2422 000061C7 E800DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2423                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2424                              <1> sndc6:
  2425 000061CC 3C80                <1> 	cmp	al, 80h
  2426 000061CE 7332                <1> 	jnb	short sndc7		
  2427                              <1> 	;
  2428 000061D0 803D[F76C0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2429 000061D7 7244                <1> 	jb	short sndc8 	; no, normal character
  2430 000061D9 883D[F76C0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2431                              <1> 	; 17/11/2015
  2432 000061DF E88AEDFFFF          <1> 	call	idle
  2433                              <1> 	;
  2434 000061E4 38BB[FA6C0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2435                              <1>         ;ja	sndc2       ; response (will be followed by
  2436                              <1> 			    ; a normal character)
  2437                              <1> 	; 24/12/2021
  2438 000061EA 7602                <1> 	jna	short sndc_10
  2439 000061EC EB82                <1> 	jmp	sndc2
  2440                              <1> sndc_10:
  2441                              <1> 	; Query request must be responded by the terminal
  2442                              <1> 	; before sending a normal character !
  2443 000061EE 53                  <1> 	push	ebx
  2444                              <1> 	;push	cx ; *** cl = character (to be sent)
  2445                              <1> 	; 24/12/2021
  2446 000061EF 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2447 000061F0 8A25[A0700000]      <1> 	mov	ah, [u.ttyn]
  2448 000061F6 E800EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2449                              <1> 		      ; received data available interrupt
  2450                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2451                              <1> 	; 24/12/2021
  2452 000061FB 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2453 000061FC 5B                  <1> 	pop	ebx
  2454 000061FD E93DFFFFFF          <1>         jmp	sndcx
  2455                              <1> sndc7:
  2456                              <1> 	 ; 16/11/2015
  2457 00006202 803D[F76C0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2458 00006209 7213                <1> 	jb	short sndc9 	; no
  2459                              <1> 	;
  2460 0000620B 88BB[F86C0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2461 00006211 88BB[FA6C0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2462                              <1> 	;
  2463 00006217 883D[F76C0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2464                              <1> sndc8:
  2465 0000621D F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2466                              <1> sndc9:
  2467                              <1> 	; AL = Line status, AH = Modem status
  2468 0000621E C3                  <1> 	retn
  2469                              <1> 
  2470                              <1> get_cpos:
  2471                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2472                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2473                              <1> 	;
  2474                              <1> 	; INPUT -> bl = video page number
  2475                              <1> 	; RETURN -> dx = cursor position
  2476                              <1> 
  2477 0000621F 53                  <1> 	push	ebx
  2478 00006220 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2479 00006223 D0E3                <1> 	shl	bl, 1
  2480 00006225 81C3[A66C0000]      <1> 	add	ebx, cursor_posn
  2481 0000622B 668B13              <1> 	mov	dx, [ebx]
  2482 0000622E 5B                  <1> 	pop	ebx
  2483 0000622F C3                  <1> 	retn
  2484                              <1> 
  2485                              <1> read_ac_current:
  2486                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2487                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2488                              <1> 	;
  2489                              <1> 	; INPUT -> bl = video page number
  2490                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2491                              <1> 
  2492 00006230 E8F2B2FFFF          <1> 	call 	find_position ; 'video.inc'
  2493                              <1> 	; dx = status port
  2494                              <1> 	; esi = cursor location/address
  2495 00006235 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2496 0000623B 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2497 0000623E C3                  <1> 	retn
  2498                              <1> 
  2499                              <1> syssleep:
  2500                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2501                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2502                              <1> 	;
  2503                              <1> 	; Retro UNIX 8086 v1 feature only
  2504                              <1> 	; (INPUT -> none)
  2505                              <1> 	;
  2506 0000623F 0FB61D[9B700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2507 00006246 8AA3[A76D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2508 0000624C E8AAEDFFFF          <1> 	call	sleep
  2509 00006251 E989D8FFFF          <1> 	jmp	sysret
  2510                              <1> 
  2511                              <1> 	; 27/02/2022
  2512                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2513                              <1> %if 0
  2514                              <1> 
  2515                              <1> vp_clr:
  2516                              <1> 	; Reset/Clear Video Page
  2517                              <1> 	;
  2518                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2519                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2520                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2521                              <1> 	;
  2522                              <1> 	; Retro UNIX 8086 v1 feature only !
  2523                              <1> 	;
  2524                              <1> 	; INPUTS -> 
  2525                              <1> 	;   BL = video page number	 
  2526                              <1> 	;
  2527                              <1> 	; OUTPUT ->
  2528                              <1> 	;   none
  2529                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2530                              <1> 	;
  2531                              <1> 	; 04/12/2013
  2532                              <1> 	sub	al, al
  2533                              <1> 	; al = 0 (clear video page)
  2534                              <1> 	; bl = video page
  2535                              <1> 	mov	ah, 07h
  2536                              <1> 	; ah = 7 (attribute/color)
  2537                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2538                              <1> 	; 24/12/2021
  2539                              <1> 	xor	ecx, ecx
  2540                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2541                              <1> 	call	scroll_up
  2542                              <1> 	; bl = video page
  2543                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2544                              <1> 	; 24/12/2021
  2545                              <1> 	xor	edx, edx 
  2546                              <1> 	jmp 	set_cpos
  2547                              <1> 
  2548                              <1> %endif
  2549                              <1> 
  2550                              <1> sysmsg:
  2551                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2552                              <1> 	; 11/11/2015
  2553                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2554                              <1> 	; Print user-application message on user's console tty
  2555                              <1> 	;
  2556                              <1> 	; Input -> EBX = Message address
  2557                              <1> 	;	   ECX = Message length (max. 255)
  2558                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2559                              <1> 	;
  2560 00006256 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2561                              <1> 	;ja	sysret ; nothing to do with big message size
  2562 0000625C 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2563 0000625E 08C9                <1> 	or	cl, cl
  2564                              <1> 	;jz	sysret
  2565 00006260 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2566 00006262 20D2                <1> 	and	dl, dl
  2567 00006264 7502                <1> 	jnz	short sysmsg0
  2568 00006266 B207                <1> 	mov	dl, 07h ; default color
  2569                              <1> 		; (black background, light gray character)
  2570                              <1> sysmsg0:
  2571 00006268 891D[6C700000]      <1> 	mov	[u.base], ebx
  2572 0000626E 8815[B76C0000]      <1> 	mov	[ccolor], dl ; color attributes
  2573 00006274 89E5                <1> 	mov	ebp, esp
  2574 00006276 31DB                <1> 	xor	ebx, ebx ; 0
  2575 00006278 891D[74700000]      <1> 	mov	[u.nread], ebx ; 0
  2576                              <1> 	;
  2577 0000627E 381D[B3700000]      <1> 	cmp	[u.kcall], bl ; 0
  2578 00006284 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2579                              <1> 	;
  2580 00006286 890D[70700000]      <1> 	mov	[u.count], ecx
  2581 0000628C 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2582                              <1> 	; 24/12/2021
  2583                              <1> 	; (dword alignment for esp)
  2584 0000628D F6C103              <1> 	test	cl, 3
  2585 00006290 7404                <1> 	jz	short sysmsg_7
  2586 00006292 80C903              <1> 	or	cl, 3
  2587 00006295 41                  <1> 	inc	ecx
  2588                              <1> sysmsg_7:
  2589 00006296 29CC                <1> 	sub	esp, ecx
  2590 00006298 89E7                <1> 	mov	edi, esp
  2591 0000629A 89E6                <1> 	mov	esi, esp
  2592 0000629C 66891D[B1700000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2593                              <1> 	; 11/11/2015
  2594 000062A3 8A25[7C700000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2595                              <1> 	; 0 = none
  2596 000062A9 FECC                <1> 	dec	ah
  2597 000062AB 790C                <1> 	jns	short sysmsg1 
  2598 000062AD 8A1D[9B700000]      <1> 	mov	bl, [u.uno] ; process number	
  2599 000062B3 8AA3[A76D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2600                              <1> sysmsg1:
  2601 000062B9 8825[A0700000]      <1> 	mov	[u.ttyn], ah
  2602                              <1> sysmsg2:
  2603 000062BF E804F5FFFF          <1> 	call	cpass
  2604 000062C4 7416                <1> 	jz	short sysmsg5
  2605 000062C6 AA                  <1> 	stosb
  2606 000062C7 20C0                <1> 	and	al, al
  2607 000062C9 75F4                <1> 	jnz	short sysmsg2
  2608                              <1> sysmsg3:
  2609 000062CB 80FC07              <1> 	cmp	ah, 7 ; tty number
  2610 000062CE 7711                <1> 	ja	short sysmsg6 ; serial port
  2611 000062D0 E83E000000          <1> 	call	print_cmsg
  2612                              <1> sysmsg4:
  2613 000062D5 89EC                <1> 	mov	esp, ebp	
  2614                              <1> sysmsg8: ; 24/12/2021	
  2615 000062D7 E903D8FFFF          <1> 	jmp	sysret
  2616                              <1> sysmsg5:
  2617 000062DC C60700              <1> 	mov	byte [edi], 0
  2618 000062DF EBEA                <1> 	jmp	short sysmsg3
  2619                              <1> sysmsg6:
  2620 000062E1 8A06                <1> 	mov	al, [esi]
  2621 000062E3 E843FEFFFF          <1> 	call	sndc
  2622 000062E8 72EB                <1> 	jc	short sysmsg4
  2623 000062EA 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2624 000062ED 76E6                <1> 	jna	short sysmsg4
  2625 000062EF 46                  <1> 	inc 	esi
  2626 000062F0 8A25[A0700000]      <1> 	mov	ah, [u.ttyn]
  2627 000062F6 EBE9                <1> 	jmp	short sysmsg6
  2628                              <1> 
  2629                              <1> sysmsgk: ; Temporary (01/07/2015)
  2630                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2631                              <1> 	; (ECX -character count- will not be considered)
  2632 000062F8 8B35[6C700000]      <1> 	mov	esi, [u.base]
  2633 000062FE 8A25[B66C0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2634 00006304 8825[A0700000]      <1> 	mov	[u.ttyn], ah
  2635 0000630A C605[B3700000]00    <1> 	mov	byte [u.kcall], 0
  2636 00006311 EBB8                <1> 	jmp	short sysmsg3
  2637                              <1> 	
  2638                              <1> print_cmsg: 
  2639                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2640                              <1> 	;
  2641                              <1> 	; print message (on user's console tty) 
  2642                              <1> 	;	with requested color
  2643                              <1> 	;
  2644                              <1> 	; INPUTS:
  2645                              <1> 	;	esi = message address
  2646                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2647                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2648                              <1> 	;
  2649 00006313 AC                  <1> 	lodsb
  2650                              <1> pcmsg1:
  2651 00006314 56                  <1> 	push 	esi
  2652 00006315 0FB61D[A0700000]    <1>         movzx   ebx, byte [u.ttyn]
  2653 0000631C 8A25[B76C0000]      <1> 	mov	ah, [ccolor]
  2654 00006322 E89AB0FFFF          <1> 	call 	write_tty
  2655 00006327 5E                  <1> 	pop	esi
  2656 00006328 AC                  <1> 	lodsb
  2657 00006329 20C0                <1> 	and 	al, al  ; 0
  2658 0000632B 75E7                <1> 	jnz 	short pcmsg1
  2659 0000632D C3                  <1> 	retn
  2660                              <1> 
  2661                              <1> sysgeterr:
  2662                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2663                              <1> 	; 09/12/2015
  2664                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2665                              <1> 	; Get last error number or page fault count
  2666                              <1> 	; (for debugging)
  2667                              <1> 	;
  2668                              <1> 	; Input -> EBX = return type
  2669                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2670                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2671                              <1> 	;	   FFFFFFFEh = total page fault count
  2672                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2673                              <1> 	;
  2674                              <1> 	; Output -> EAX = last error number or page fault count
  2675                              <1> 	;	   (depending on EBX input)
  2676                              <1> 	; 	
  2677 0000632E 21DB                <1> 	and 	ebx, ebx
  2678 00006330 750F                <1> 	jnz	short glerr_2
  2679                              <1> glerr_0:
  2680 00006332 A1[A1700000]        <1> 	mov	eax, [u.error]
  2681                              <1> glerr_1:
  2682 00006337 A3[4C700000]        <1> 	mov	[u.r0], eax
  2683                              <1>  	;retn
  2684                              <1> 	; 16/02/2022 (BugFix)
  2685 0000633C E99ED7FFFF          <1> 	jmp	sysret
  2686                              <1> glerr_2:
  2687 00006341 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2688 00006342 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2689 00006344 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2690 00006345 75EB                <1> 	jnz	short glerr_0
  2691 00006347 A1[406D0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2692 0000634C EBE9                <1>         jmp     short glerr_1
  2693                              <1> glerr_3:
  2694 0000634E A1[B5700000]        <1> 	mov 	eax, [u.pfcount]
  2695 00006353 EBE2                <1> 	jmp	short glerr_1
  2696                              <1> 
  2697                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2698                              <1> ;	     - PRINTER BIOS (Functions)		
  2699                              <1> 
  2700                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2701                              <1> ;
  2702                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2703                              <1> ; PRINTER_IO								       :
  2704                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2705                              <1> ; INPUT 								       :
  2706                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2707                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2708                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2709                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2710                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2711                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2712                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2713                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2714                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2715                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2716                              <1> ;		   |	   |	   |	   |	   |			       :
  2717                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2718                              <1> ;		   |	   |	   |	   |				       :
  2719                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2720                              <1> ;		   |	   |	   |					       :
  2721                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2722                              <1> ;		   |	   |						       :
  2723                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2724                              <1> ;		   |							       :
  2725                              <1> ;		   |_ 1 = NOT BUSY					       :
  2726                              <1> ;									       :
  2727                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2728                              <1> ;		IN @PRINTER_BASE AREA					       :
  2729                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2730                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2731                              <1> ;									       :
  2732                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2733                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2734                              <1> ;									       :
  2735                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2736                              <1> ;		ALL OTHERS UNCHANGED					       :
  2737                              <1> ;-------------------------------------------------------------------------------
  2738                              <1> 
  2739                              <1> int17h:
  2740                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2741                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2742                              <1> 	;
  2743                              <1> 	; (Default printer port: 378h) ; LPT1
  2744                              <1> 	; (Number of printers = 1)
  2745                              <1> 	
  2746                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2747                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2748                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2749                              <1> 
  2750                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2751                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2752                              <1> 
  2753                              <1> 	; INPUT:
  2754                              <1> 	;	ah = 0 -> print the character in AL 
  2755                              <1> 	;		 (sys write with write count >0)
  2756                              <1> 	;	ah = 1 -> initialize printer port
  2757                              <1> 	;		 (sys open)	
  2758                              <1> 	;	ah = 2 -> read the printer status 
  2759                              <1> 	;		 (sys write with write count = 0)
  2760                              <1> 	; OUTPUT:
  2761                              <1> 	;	ah = printer status
  2762                              <1> 
  2763                              <1> 	; Modified registers: eax, ecx, edx
  2764                              <1> 
  2765                              <1> PRINTER_IO_1:
  2766 00006355 08E4                <1> 	or	ah, ah
  2767 00006357 7417                <1> 	jz	short _b20
  2768 00006359 FECC                <1> 	dec	ah
  2769 0000635B 7444                <1> 	jz	short _b80
  2770                              <1> 	;dec 	ah
  2771                              <1> 	;jz	short _b50
  2772                              <1> _b50:
  2773                              <1> 	;-----	PRINTER STATUS
  2774                              <1> B50:
  2775 0000635D 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2776                              <1> B60:
  2777 0000635E 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2778                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2779                              <1> 				; POINT TO CONTROL PORT
  2780 00006362 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2781 00006363 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2782 00006364 88C4                <1> 	mov	ah, al		; SAVE
  2783 00006366 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2784                              <1> B70:
  2785 00006369 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2786 0000636A 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2787 0000636C 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2788                              <1> B10:
  2789 0000636F C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2790                              <1> _b20:
  2791                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2792 00006370 B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2793                              <1> B20:
  2794 00006375 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2795 00006376 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2796 0000637A EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2797 0000637B FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2798                              <1> 
  2799                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2800                              <1> B25:
  2801                              <1> 	;-----	WAIT BUSY
  2802                              <1> B35:
  2803 0000637D EC                  <1> 	in	al, dx		; GET STATUS
  2804 0000637E 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2805 00006380 A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2806 00006382 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2807 00006384 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2808 00006389 E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2809                              <1> 
  2810 0000638B 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2811 0000638E 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2812 00006391 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2813                              <1> 
  2814                              <1> B40:				; SEND STROBE PULSE
  2815 00006393 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2816 00006395 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2817 00006397 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2818 00006398 EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2819                              <1> 	; IODELAY
  2820                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2821                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2822                              <1> 	; NEWIODELAY
  2823 00006399 E6EB                <1> 	out	0EBh, al
  2824                              <1> 
  2825 0000639B B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2826 0000639D EE                  <1> 	out	dx, al
  2827 0000639E FB                  <1> 	sti			; INTERRUPTS BACK ON
  2828                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2829                              <1> 	;jmp	short B50
  2830 0000639F EBBD                <1> 	jmp	short B60
  2831                              <1> 
  2832                              <1> _b80:
  2833                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2834                              <1> B80:
  2835 000063A1 50                  <1> 	push	eax		; SAVE (AL)
  2836 000063A2 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2837 000063A6 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2838 000063A8 EE                  <1> 	out	dx, al
  2839                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2840 000063A9 B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2841                              <1> B90:				; INIT_LOOP
  2842                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2843                              <1> 	;jnz	short B90	; INIT_LOOP
  2844 000063AE E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2845 000063B3 E2F9                <1> 	loop	B90	
  2846 000063B5 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2847 000063B7 EE                  <1> 	out	dx, al
  2848 000063B8 EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2849                              <1> 
  2850                              <1> 
  2851                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2852                              <1> ; -------------------------------------------------------------------
  2853                              <1> ;
  2854                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2855                              <1> ;;65536/30 = 2185
  2856                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2857                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2858                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2859                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2860                              <1> ;
  2861                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2862                              <1> ;
  2863                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2864                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2865                              <1> ;;1,080,000 / 30 = 36,000
  2866                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2867                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2868                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2869                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2870                              <1> ;
  2871                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2872                              <1> 
  2873                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2874                              <1> ; ------------------------------------------
  2875                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2876                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2877                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2878                              <1> ;	OUTPUT: BX:CX destroyed.
  2879                              <1> ;
  2880                              <1> ;	SAVES:	AX (except when NO STACK)
  2881                              <1> ;
  2882                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2883                              <1> ;		used this way, AX is assumed to be destroyed.
  2884                              <1> 
  2885                              <1> WAIT_REFRESH:
  2886                              <1> 	; 13/06/2022
  2887                              <1> 	; Modified for Retro UNIX 386 v1.1
  2888                              <1> 	
  2889                              <1> 	; (wait for 30 micro seconds)
  2890                              <1> 
  2891                              <1> 	SYS1	equ 61h ; PORT_B
  2892                              <1> 
  2893                              <1> WR_SHORT:
  2894 000063BA 50                  <1> 	push	eax
  2895                              <1> WR_STAT_0:
  2896 000063BB E461                <1> 	in	al, SYS1	; wait for high to low
  2897 000063BD A810                <1> 	test	al, 10h		; transition on memory
  2898 000063BF 75FA                <1> 	jnz	short WR_STAT_0 
  2899                              <1> WR_STAT_1:
  2900 000063C1 E461                <1> 	in	al, SYS1
  2901 000063C3 A810                <1> 	test	al, 10h
  2902 000063C5 74FA                <1> 	jz	short WR_STAT_1
  2903 000063C7 58                  <1> 	pop	eax
  2904 000063C8 C3                  <1> 	retn
  2111                                  
  2112                                  ; 07/03/2015
  2113                                  ; Temporary Code
  2114                                  display_disks:
  2115 000063C9 803D[7E670000]00        	cmp 	byte [fd0_type], 0
  2116 000063D0 7605                    	jna 	short ddsks1
  2117 000063D2 E87D000000              	call	pdskm
  2118                                  ddsks1:
  2119 000063D7 803D[7F670000]00        	cmp	byte [fd1_type], 0
  2120 000063DE 760C                    	jna	short ddsks2
  2121 000063E0 C605[6F690000]31        	mov	byte [dskx], '1'
  2122 000063E7 E868000000              	call	pdskm
  2123                                  ddsks2:
  2124 000063EC 803D[80670000]00        	cmp	byte [hd0_type], 0
  2125 000063F3 7654                    	jna	short ddsk6
  2126 000063F5 66C705[6D690000]68-     	mov	word [dsktype], 'hd'
  2126 000063FD 64                 
  2127 000063FE C605[6F690000]30        	mov	byte [dskx], '0'
  2128 00006405 E84A000000              	call	pdskm
  2129                                  ddsks3:
  2130 0000640A 803D[81670000]00        	cmp	byte [hd1_type], 0
  2131 00006411 7636                    	jna	short ddsk6
  2132 00006413 C605[6F690000]31        	mov	byte [dskx], '1'
  2133 0000641A E835000000              	call	pdskm
  2134                                  ddsks4:
  2135 0000641F 803D[82670000]00        	cmp	byte [hd2_type], 0
  2136 00006426 7621                    	jna	short ddsk6
  2137 00006428 C605[6F690000]32        	mov	byte [dskx], '2'
  2138 0000642F E820000000              	call	pdskm
  2139                                  ddsks5:
  2140 00006434 803D[83670000]00        	cmp	byte [hd3_type], 0
  2141 0000643B 760C                    	jna	short ddsk6
  2142 0000643D C605[6F690000]33        	mov	byte [dskx], '3'
  2143 00006444 E80B000000              	call	pdskm
  2144                                  ddsk6:
  2145 00006449 BE[7E690000]            	mov	esi, nextline
  2146 0000644E E806000000              	call	pdskml
  2147                                  pdskm_ok:
  2148 00006453 C3                      	retn
  2149                                  pdskm:
  2150 00006454 BE[6B690000]            	mov	esi, dsk_ready_msg
  2151                                  pdskml:	
  2152 00006459 AC                      	lodsb
  2153 0000645A 08C0                    	or	al, al
  2154 0000645C 74F5                    	jz	short pdskm_ok
  2155 0000645E 56                      	push	esi
  2156 0000645F 31DB                    	xor	ebx, ebx ; 0
  2157                                  			; Video page 0 (bl=0)
  2158 00006461 B407                    	mov	ah, 07h ; Black background, 
  2159                                  			; light gray forecolor
  2160 00006463 E859AFFFFF              	call	write_tty
  2161 00006468 5E                      	pop	esi
  2162 00006469 EBEE                    	jmp	short pdskml
  2163                                  
  2164 0000646B 90<rep 5h>              align 16
  2165                                  
  2166                                  gdt:	; Global Descriptor Table
  2167                                  	; (30/07/2015, conforming cs)
  2168                                  	; (26/03/2015)
  2169                                  	; (24/03/2015, tss)
  2170                                  	; (19/03/2015)
  2171                                  	; (29/12/2013)
  2172                                  	;
  2173 00006470 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2174                                  	; 18/08/2014
  2175                                  			; 8h kernel code segment, base = 00000000h		
  2176 00006478 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2177                                  			; 10h kernel data segment, base = 00000000h	
  2178 00006480 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2179                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2180 00006488 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2181                                  			; 23h user data segment, base address = 400000h ; CORE
  2182 00006490 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2183                                  			; Task State Segment
  2184 00006498 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2185                                  			       ;  no IO permission in ring 3)
  2186                                  gdt_tss0:
  2187 0000649A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2188                                  gdt_tss1:
  2189 0000649C 00                      	db 0  ; TSS base address, bits 16-23 
  2190                                  	      		; 49h	
  2191 0000649D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2192 0000649E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2193                                  gdt_tss2:
  2194 0000649F 00                      	db 0  ; TSS base address, bits 24-31 
  2195                                  
  2196                                  gdt_end:
  2197                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2198                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2199                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2200                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2201                                  
  2202                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2203                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2204                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2205                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2206                                  		; W= Writeable, A= Accessed
  2207                                  	
  2208                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2209                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2210                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2211                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2212                                  
  2213                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2214                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2215                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2216                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2217                                  	
  2218                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2219                                  
  2220                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2221                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2222                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2223                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2224                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2225                                  		; AVL= Available to programmers	
  2226                                  
  2227                                  gdtd:
  2228 000064A0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2229 000064A2 [70640000]                      dd gdt			; Address of the GDT
  2230                                  
  2231                                  	; 20/08/2014
  2232                                  idtd:
  2233 000064A6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2234 000064A8 [206A0000]                      dd idt			; Address of the IDT
  2235                                  
  2236                                  Align 4
  2237                                  
  2238                                  	; 21/08/2014
  2239                                  ilist:
  2240                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2241                                  	;
  2242                                  	; Exception list
  2243                                  	; 25/08/2014	
  2244 000064AC [24080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2245 000064B0 [2B080000]              	dd	exc1	
  2246 000064B4 [32080000]              	dd 	exc2	
  2247 000064B8 [39080000]              	dd	exc3	
  2248 000064BC [3D080000]              	dd	exc4	
  2249 000064C0 [41080000]              	dd	exc5	
  2250 000064C4 [45080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2251 000064C8 [49080000]              	dd	exc7	
  2252 000064CC [4D080000]              	dd	exc8	
  2253 000064D0 [51080000]              	dd	exc9	
  2254 000064D4 [55080000]              	dd 	exc10	
  2255 000064D8 [59080000]              	dd	exc11
  2256 000064DC [5D080000]              	dd	exc12
  2257 000064E0 [61080000]              	dd	exc13	; 0Dh, General Protection Fault
  2258 000064E4 [65080000]              	dd 	exc14	; 0Eh, Page Fault
  2259 000064E8 [69080000]              	dd	exc15
  2260 000064EC [6D080000]              	dd	exc16
  2261 000064F0 [71080000]              	dd	exc17
  2262 000064F4 [75080000]              	dd 	exc18
  2263 000064F8 [79080000]              	dd	exc19
  2264 000064FC [7D080000]              	dd 	exc20
  2265 00006500 [81080000]              	dd	exc21
  2266 00006504 [85080000]              	dd	exc22
  2267 00006508 [89080000]              	dd	exc23
  2268 0000650C [8D080000]              	dd 	exc24
  2269 00006510 [91080000]              	dd	exc25
  2270 00006514 [95080000]              	dd	exc26
  2271 00006518 [99080000]              	dd	exc27
  2272 0000651C [9D080000]              	dd 	exc28
  2273 00006520 [A1080000]              	dd	exc29
  2274 00006524 [A5080000]              	dd 	exc30
  2275 00006528 [A9080000]              	dd	exc31
  2276                                  	; Interrupt list
  2277 0000652C [5F060000]              	dd	timer_int	; INT 20h
  2278                                  		;dd	irq0	
  2279 00006530 [630B0000]              	dd	keyb_int	; 27/08/2014
  2280                                  		;dd	irq1
  2281 00006534 [7E070000]              	dd	irq2
  2282                                  		; COM2 int
  2283 00006538 [82070000]              	dd	irq3
  2284                                  		; COM1 int
  2285 0000653C [8D070000]              	dd	irq4
  2286 00006540 [98070000]              	dd	irq5
  2287                                  ;DISKETTE_INT: ;06/02/2015
  2288 00006544 [40250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2289                                  		;dd	irq6
  2290                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2291                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2292 00006548 [140B0000]              	dd	default_irq7	; 25/02/2015
  2293                                  		;dd	irq7
  2294                                  ; Real Time Clock Interrupt
  2295 0000654C [B2090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2296                                  		;dd	irq8	; INT 28h
  2297 00006550 [A8070000]              	dd	irq9
  2298 00006554 [AC070000]              	dd	irq10
  2299 00006558 [B0070000]              	dd	irq11
  2300 0000655C [B4070000]              	dd	irq12
  2301 00006560 [B8070000]              	dd	irq13
  2302                                  ;HDISK_INT1:  ;06/02/2015 	
  2303 00006564 [672D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2304                                  		;dd	irq14
  2305                                  ;HDISK_INT2:  ;06/02/2015
  2306 00006568 [8A2D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2307                                  		;dd	irq15	; INT 2Fh
  2308                                  		; 14/08/2015
  2309 0000656C [C7390000]              	dd	sysent		; INT 30h (system calls)
  2310                                  	
  2311                                  	;dd	ignore_int
  2312 00006570 00000000                	dd	0
  2313                                  
  2314                                  ;;;
  2315                                  ;;; 11/03/2015
  2316                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2317                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KYBDATA.INC
  2318                              <1> ; Last Modification: 13/06/2022
  2319                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2320                              <1> ;
  2321                              <1> ; ///////// KEYBOARD DATA ///////////////
  2322                              <1> 
  2323                              <1> ; 11/03/2015
  2324                              <1> ; 05/12/2014
  2325                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2326                              <1> ; 03/06/86  KEYBOARD BIOS
  2327                              <1> 
  2328                              <1> ;---------------------------------------------------------------------------------
  2329                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2330                              <1> ;---------------------------------------------------------------------------------
  2331                              <1> 
  2332                              <1> ;-----	TABLES FOR ALT CASE ------------
  2333                              <1> ;-----	ALT-INPUT-TABLE 
  2334 00006574 524F50514B          <1> K30:	db	82,79,80,81,75
  2335 00006579 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2336                              <1> ;-----	SUPER-SHIFT-TABLE 
  2337 0000657E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2338 00006584 161718191E1F        <1> 	db	22,23,24,25,30,31
  2339 0000658A 202122232425        <1> 	db	32,33,34,35,36,37
  2340 00006590 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2341 00006596 3132                <1> 	db	49,50
  2342                              <1> 
  2343                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2344                              <1> ;-----	KEY_TABLE 
  2345 00006598 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2346 00006599 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2347 0000659E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2348                              <1> _K6L    equ     $-_K6
  2349                              <1> 
  2350                              <1> ;-----	MASK_TABLE
  2351 000065A0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2352 000065A1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2353 000065A6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2354                              <1> 
  2355                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2356 000065A8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2357 000065AE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2358                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2359 000065B4 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2360 000065BA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2361 000065C0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2362 000065C6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2363 000065CC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2364 000065D2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2365 000065D8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2366 000065DE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2367                              <1> 	;				;----- FUNCTIONS ------		
  2368 000065E2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2369 000065E8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2370 000065EE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2371 000065F4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2372 000065FA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2373                              <1> 
  2374                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2375 00006600 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2375 00006609 39302D3D0809        <1>
  2376 0000660F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2376 00006618 705B5D0DFF61736466- <1>
  2376 00006621 67686A6B6C3B27      <1>
  2377 00006628 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2377 00006631 6D2C2E2FFF2AFF20FF  <1>
  2378                              <1> ;-----	LC TABLE SCAN
  2379 0000663A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2380 0000663F 4041424344          <1> 	db	64,65,66,67,68
  2381 00006644 FFFF                <1> 	db	-1,-1			; NL, SL
  2382                              <1> 
  2383                              <1> ;-----	KEYPAD TABLE
  2384 00006646 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2385 0000664C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2386 00006653 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2387                              <1> 
  2388                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2389 00006658 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2389 00006661 28295F2B0800        <1>
  2390 00006667 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2390 00006670 507B7D0DFF41534446- <1>
  2390 00006679 47484A4B4C3A22      <1>
  2391 00006680 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2391 00006689 4D3C3E3FFF2AFF20FF  <1>
  2392                              <1> ;-----	UC TABLE SCAN
  2393 00006692 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2394 00006697 595A5B5C5D          <1> 	db	89,90,91,92,93
  2395 0000669C FFFF                <1> 	db	-1,-1			; NL, SL
  2396                              <1> 
  2397                              <1> ;-----	NUM STATE TABLE
  2398 0000669E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2398 000066A7 3233302E            <1>
  2399                              <1> 	;
  2400 000066AB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2401                              <1> 
  2402                              <1> Align	4
  2403                              <1> ;----------------------------------------
  2404                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2405                              <1> ;----------------------------------------
  2406 000066B0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2407 000066B1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2408                              <1> 				; (29h default setting for video mode 3)
  2409                              <1> 				; Mode Select register Bits
  2410                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2411                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2412                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2413                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2414                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2415                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2416                              <1> 				;   BIT 6, 7 - Not Used
  2417                              <1> 
  2418                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2419                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2420                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2421                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2422                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2423                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2424                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2425                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2426                              <1> ; Mode & 37h = Video signal OFF
  2427                              <1> 			
  2428                              <1> 
  2429                              <1> ; 26/08/2014
  2430                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2431                              <1> ; Derived from IBM "pc-at" 
  2432                              <1> ; rombios source code (06/10/1985)
  2433                              <1> ; 'dseg.inc'
  2434                              <1> 
  2435                              <1> ;---------------------------------------;
  2436                              <1> ;	SYSTEM DATA AREA		;
  2437                              <1> ;----------------------------------------
  2438 000066B2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2439                              <1> 
  2440                              <1> ;----------------------------------------
  2441                              <1> ;	KEYBOARD DATA AREAS		;
  2442                              <1> ;----------------------------------------
  2443                              <1> 
  2444 000066B3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2445 000066B4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2446 000066B5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2447 000066B6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2448 000066B7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2449 000066B8 [C8660000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2450 000066BC [E8660000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2451 000066C0 [C8660000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2452 000066C4 [C8660000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2453                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2454 000066C8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2455                              <1> 
  2456                              <1> ; /// End Of KEYBOARD DATA ///
  2317                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2318                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2319                              <1> ; Last Modification: 11/03/2015
  2320                              <1> ;		    (Data section for 'VIDEO.INC')	
  2321                              <1> ;
  2322                              <1> ; ///////// VIDEO DATA ///////////////
  2323                              <1> 
  2324                              <1> video_params:
  2325                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2326                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2327                              <1> 	; VIDEO MODE 3
  2328 000066E8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2329 000066EF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2330 000066F4 00000000            <1> 	db	0,0,0,0
  2331                              <1> 
  2332                              <1> ; /// End Of VIDEO DATA ///
  2318                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2319                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2320                              <1> ; Last Modification: 11/03/2015
  2321                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2322                              <1> ;
  2323                              <1> ; *****************************************************************************
  2324                              <1> 
  2325                              <1> ;----------------------------------------
  2326                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2327                              <1> ;	REFERENCED BY POST & BIOS	:
  2328                              <1> ;----------------------------------------
  2329                              <1> 
  2330 000066F8 [5B670000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2331                              <1> 
  2332                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2333                              <1> ;----------------------------------------------------------------
  2334                              <1> ; DISK_BASE							:
  2335                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2336                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2337                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2338                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2339                              <1> ;----------------------------------------------------------------
  2340                              <1> 
  2341                              <1> ;DISK_BASE:	
  2342                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2343                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2344                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2345                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2346                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2347                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2348                              <1> ;	DB	01BH		; GAP LENGTH
  2349                              <1> ;	DB	0FFH		; DTL
  2350                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2351                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2352                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2353                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2354                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2355                              <1> 
  2356                              <1> ;----------------------------------------
  2357                              <1> ;	ROM BIOS DATA AREAS		:
  2358                              <1> ;----------------------------------------
  2359                              <1> 
  2360                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2361                              <1> 
  2362                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2363                              <1> 
  2364                              <1> ;----------------------------------------
  2365                              <1> ;	DISKETTE DATA AREAS		:
  2366                              <1> ;----------------------------------------
  2367                              <1> 
  2368                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2369                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2370                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2371                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2372                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2373                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2374                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2375                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2376                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2377                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2378                              <1> 
  2379                              <1> ;----------------------------------------
  2380                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2381                              <1> ;----------------------------------------
  2382                              <1> 
  2383                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2384                              <1> 
  2385                              <1> ;----------------------------------------
  2386                              <1> ;	TIMER DATA AREA 		:
  2387                              <1> ;----------------------------------------
  2388                              <1> 
  2389                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2390                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2391                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2392                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2393                              <1> 
  2394                              <1> ;----------------------------------------
  2395                              <1> ;	ADDITIONAL MEDIA DATA		:
  2396                              <1> ;----------------------------------------
  2397                              <1> 
  2398                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2399                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2400                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2401                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2402                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2403                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2404                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2405                              <1> 
  2406                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2407                              <1> 
  2408                              <1> ;--------------------------------------------------------
  2409                              <1> ;	DRIVE TYPE TABLE				:
  2410                              <1> ;--------------------------------------------------------
  2411                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2412                              <1> DR_TYPE:
  2413 000066FC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2414                              <1>                 ;DW      MD_TBL1
  2415 000066FD [1A670000]          <1> 		dd	MD_TBL1
  2416 00006701 82                  <1> 		DB	02+BIT7ON
  2417                              <1> 		;DW      MD_TBL2
  2418 00006702 [27670000]          <1>                 dd      MD_TBL2
  2419 00006706 02                  <1> DR_DEFAULT:	DB	02
  2420                              <1>                 ;DW      MD_TBL3
  2421 00006707 [34670000]          <1> 		dd      MD_TBL3
  2422 0000670B 03                  <1> 		DB	03
  2423                              <1>                 ;DW      MD_TBL4
  2424 0000670C [41670000]          <1> 		dd      MD_TBL4
  2425 00006710 84                  <1> 		DB	04+BIT7ON
  2426                              <1>                 ;DW      MD_TBL5
  2427 00006711 [4E670000]          <1> 		dd      MD_TBL5
  2428 00006715 04                  <1> 		DB	04
  2429                              <1>                 ;DW      MD_TBL6
  2430 00006716 [5B670000]          <1> 		dd      MD_TBL6
  2431                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2432                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2433                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2434                              <1> ;--------------------------------------------------------
  2435                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2436                              <1> ;--------------------------------------------------------
  2437                              <1> ;--------------------------------------------------------
  2438                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2439                              <1> ;--------------------------------------------------------
  2440                              <1> MD_TBL1:        
  2441 0000671A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2442 0000671B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2443 0000671C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2444 0000671D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2445 0000671E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2446 0000671F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2447 00006720 FF                  <1> 	DB	0FFH		; DTL
  2448 00006721 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2449 00006722 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2450 00006723 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2451 00006724 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2452 00006725 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2453 00006726 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2454                              <1> ;--------------------------------------------------------
  2455                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2456                              <1> ;--------------------------------------------------------
  2457                              <1> MD_TBL2:        
  2458 00006727 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2459 00006728 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2460 00006729 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2461 0000672A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2462 0000672B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2463 0000672C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2464 0000672D FF                  <1> 	DB	0FFH		; DTL
  2465 0000672E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2466 0000672F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2467 00006730 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2468 00006731 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2469 00006732 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2470 00006733 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2471                              <1> ;--------------------------------------------------------
  2472                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2473                              <1> ;--------------------------------------------------------
  2474                              <1> MD_TBL3:
  2475 00006734 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2476 00006735 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2477 00006736 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2478 00006737 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2479 00006738 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2480 00006739 1B                  <1> 	DB	01BH		; GAP LENGTH
  2481 0000673A FF                  <1> 	DB	0FFH		; DTL
  2482 0000673B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2483 0000673C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2484 0000673D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2485 0000673E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2486 0000673F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2487 00006740 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2488                              <1> ;--------------------------------------------------------
  2489                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2490                              <1> ;--------------------------------------------------------
  2491                              <1> MD_TBL4:
  2492 00006741 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2493 00006742 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2494 00006743 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2495 00006744 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2496 00006745 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2497 00006746 2A                  <1> 	DB	02AH		; GAP LENGTH
  2498 00006747 FF                  <1> 	DB	0FFH		; DTL
  2499 00006748 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2500 00006749 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2501 0000674A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2502 0000674B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2503 0000674C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2504 0000674D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2505                              <1> ;--------------------------------------------------------
  2506                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2507                              <1> ;--------------------------------------------------------
  2508                              <1> MD_TBL5:
  2509 0000674E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2510 0000674F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2511 00006750 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2512 00006751 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2513 00006752 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2514 00006753 2A                  <1> 	DB	02AH		; GAP LENGTH
  2515 00006754 FF                  <1> 	DB	0FFH		; DTL
  2516 00006755 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2517 00006756 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2518 00006757 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2519 00006758 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2520 00006759 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2521 0000675A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2522                              <1> ;--------------------------------------------------------
  2523                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2524                              <1> ;--------------------------------------------------------
  2525                              <1> MD_TBL6:
  2526 0000675B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2527 0000675C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2528 0000675D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2529 0000675E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2530 0000675F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2531 00006760 1B                  <1> 	DB	01BH		; GAP LENGTH
  2532 00006761 FF                  <1> 	DB	0FFH		; DTL
  2533 00006762 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2534 00006763 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2535 00006764 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2536 00006765 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2537 00006766 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2538 00006767 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2539                              <1> 
  2540                              <1> 
  2541                              <1> ; << diskette.inc >>
  2542                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2543                              <1> ;
  2544                              <1> ;----------------------------------------
  2545                              <1> ;	ROM BIOS DATA AREAS		:
  2546                              <1> ;----------------------------------------
  2547                              <1> 
  2548                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2549                              <1> 
  2550                              <1> ;----------------------------------------
  2551                              <1> ;	FIXED DISK DATA AREAS		:
  2552                              <1> ;----------------------------------------
  2553                              <1> 
  2554                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2555                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2556                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2557                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2558                              <1> 
  2559                              <1> ;----------------------------------------
  2560                              <1> ;	ADDITIONAL MEDIA DATA		:
  2561                              <1> ;----------------------------------------
  2562                              <1> 
  2563                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2564                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2565                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2566                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2567                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2568                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2569                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2570                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2571                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2572                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2573                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2574                              <1> 
  2575                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2576                              <1> ;
  2577                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2578                              <1> 
  2579                              <1> ERR_TBL:
  2580 00006768 E0                  <1> 	db	NO_ERR
  2581 00006769 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2582 0000676D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2583                              <1> 
  2584                              <1> ; 17/12/2014 (mov ax, [cfd])
  2585                              <1> ; 11/12/2014
  2586 00006771 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2587                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2588 00006772 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2589                              <1> 					; (initial value of 'pfd 
  2590                              <1> 					; must be different then 'cfd' value
  2591                              <1> 					; to force updating/initializing
  2592                              <1> 					; current drive parameters) 
  2593 00006773 90                  <1> align 2
  2594                              <1> 
  2595 00006774 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2596                              <1> 			      ; (170h)
  2597 00006776 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2598                              <1> 
  2599                              <1> ; 05/01/2015 
  2600 00006778 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2601                              <1> 
  2602                              <1> ; *****************************************************************************
  2319                                  ;;;
  2320                                  
  2321 00006779 90                      Align 2
  2322                                  
  2323                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2324 0000677A 00                      boot_drv:    db 0 ; boot drive number (physical)
  2325                                  ; 24/11/2014
  2326 0000677B 00                      drv:	     db 0 
  2327 0000677C 00                      last_drv:    db 0 ; last hdd
  2328 0000677D 00                      hdc:         db 0  ; number of hard disk drives
  2329                                  		     ; (present/detected)
  2330                                  ;
  2331                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2332                                  ; Physical drive type & flags
  2333 0000677E 00                      fd0_type:    db 0  ; floppy drive type
  2334 0000677F 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2335                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2336                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2337                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2338                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2339 00006780 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2340 00006781 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2341 00006782 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2342 00006783 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2343                                  		     ; bit 0 - Fixed disk access subset supported
  2344                                  		     ; bit 1 - Drive locking and ejecting
  2345                                  		     ; bit 2 - Enhanced disk drive support
  2346                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2347                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2348                                  		     ; will interpret it as 'LBA ready'!)		
  2349                                  
  2350                                  ; 11/03/2015 - 10/07/2015
  2351 00006784 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2351 0000678D 0000000000         
  2352 00006792 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2352 0000679B 0000000000         
  2353 000067A0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2353 000067A9 0000000000         
  2354 000067AE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2354 000067B7 000000000000000000-
  2354 000067C0 000000000000000000-
  2354 000067C9 00                 
  2355 000067CA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2356 000067D1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2357                                  ;
  2358                                  
  2359                                  ; 27/08/2014
  2360                                  scr_row:
  2361 000067D8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2362                                  scr_col:
  2363 000067DC 00000000                	dd 0
  2364                                  
  2365                                  ;; 14/08/2015
  2366                                  ;;msgPM:
  2367                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2368                                  msgKVER:
  2369                                  	;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0
  2370                                  	;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.3 [02/06/2022]", 0
  2371 000067E0 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.4 [14/06/2022]", 0
  2371 000067E9 58203338362076312E-
  2371 000067F2 31202D204B65726E65-
  2371 000067FB 6C2076302E322E312E-
  2371 00006804 34205B31342F30362F-
  2371 0000680D 323032325D00       
  2372                                  
  2373 00006813 90                      Align 2
  2374                                  
  2375                                  ; 20/08/2014
  2376                                    ; /* This is the default interrupt "handler" :-) */ 
  2377                                    ; Linux v0.12 (head.s)
  2378                                  int_msg:
  2379 00006814 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2379 0000681D 6E7465727275707420-
  2379 00006826 212000             
  2380                                  
  2381 00006829 90                      Align 2  
  2382                                  
  2383                                  ; 21/08/2014
  2384                                  timer_msg:
  2385 0000682A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2385 00006833 542032306829202120-
  2385 0000683C 54696D657220496E74-
  2385 00006845 657272757074203A20 
  2386                                  tcountstr:
  2387 0000684E 303030303020            	db "00000 "
  2388 00006854 00                      	db 0
  2389                                  
  2390 00006855 90                      Align 2
  2391                                  	; 21/08/2014
  2392                                  exc_msg:
  2393 00006856 435055206578636570-     	db "CPU exception ! "
  2393 0000685F 74696F6E202120     
  2394                                  excnstr: 		; 25/08/2014
  2395 00006866 3F3F68202045495020-     	db "??h", "  EIP : "
  2395 0000686F 3A20               
  2396                                  EIPstr: ; 29/08/2014
  2397 00006871 00<rep Ch>              	times 12 db 0
  2398                                  rtc_msg:
  2399 0000687D 5265616C2054696D65-     	db "Real Time Clock - "
  2399 00006886 20436C6F636B202D20 
  2400                                  datestr:
  2401 0000688F 30302F30302F303030-     	db "00/00/0000"
  2401 00006898 30                 
  2402 00006899 20                      	db " "
  2403                                  daystr:
  2404 0000689A 44415920                	db "DAY "
  2405                                  timestr:	
  2406 0000689E 30303A30303A3030                db "00:00:00"
  2407 000068A6 20                      	db " "
  2408 000068A7 00                      	db 0 
  2409                                  
  2410                                  daytmp:
  2411                                  	; 28/02/2015
  2412 000068A8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2412 000068B1 4F4E20545545205745-
  2412 000068BA 442054485520465249-
  2412 000068C3 2053415420         
  2413                                  
  2414 000068C8 FF                      ptime_seconds: db 0FFh
  2415                                  
  2416                                  	; 23/02/2015
  2417                                  	; 25/08/2014
  2418                                  ;scounter:
  2419                                  ;	db 5
  2420                                  ;	db 19
  2421                                  
  2422                                  ; 02/01/2022
  2423                                  ; 05/11/2014
  2424                                  ;msg_out_of_memory:
  2425                                  ;	db 	07h, 0Dh, 0Ah
  2426                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2427                                  ; 	db	0Dh, 0Ah, 0
  2428                                  	;
  2429                                  setup_error_msg:
  2430 000068C9 0D0A                    	db 0Dh, 0Ah
  2431 000068CB 4469736B2053657475-     	db 'Disk Setup Error!' 
  2431 000068D4 70204572726F7221   
  2432 000068DC 0D0A00                  	db 0Dh, 0Ah,0
  2433                                  
  2434                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2435                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2436                                  ;	  db 0 ; upper left row (for scroll)	
  2437                                  
  2438                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2439                                  ;	  db 24 ; lower right row (for scroll)
  2440                                  
  2441                                  
  2442                                  ; 06/11/2014 (Temporary Data)
  2443                                  ; Memory Information message
  2444                                  ; 14/08/2015
  2445                                  msg_memory_info:
  2446 000068DF 07                      	db	07h
  2447 000068E0 0D0A                    	db	0Dh, 0Ah
  2448                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2449 000068E2 546F74616C206D656D-     	db	"Total memory : "
  2449 000068EB 6F7279203A20       
  2450                                  mem_total_b_str: ; 10 digits
  2451 000068F1 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2451 000068FA 302062797465730D0A 
  2452 00006903 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2452 0000690C 202020202020202020 
  2453                                  mem_total_p_str: ; 7 digits
  2454 00006915 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2454 0000691E 616765730D0A       
  2455 00006924 0D0A                    	db 	0Dh, 0Ah
  2456 00006926 46726565206D656D6F-     	db	"Free memory  : "
  2456 0000692F 727920203A20       
  2457                                  free_mem_b_str:  ; 10 digits
  2458 00006935 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2458 0000693E 3F2062797465730D0A 
  2459 00006947 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2459 00006950 202020202020202020 
  2460                                  free_mem_p_str:  ; 7 digits
  2461 00006959 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2461 00006962 616765730D0A       
  2462 00006968 0D0A00                  	db	0Dh, 0Ah, 0
  2463                                  
  2464                                  dsk_ready_msg:
  2465 0000696B 0D0A                    	db 	0Dh, 0Ah
  2466                                  dsktype:
  2467 0000696D 6664                    	db	'fd'
  2468                                  dskx:
  2469 0000696F 30                      	db	'0'
  2470 00006970 20                      	db	20h
  2471 00006971 697320524541445920-     	db 	'is READY ...'
  2471 0000697A 2E2E2E             
  2472 0000697D 00                      	db 	0
  2473                                  nextline:
  2474 0000697E 0D0A00                  	db 	0Dh, 0Ah, 0
  2475                                  
  2476                                  ; KERNEL - SYSINIT Messages
  2477                                  ; 24/08/2015
  2478                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2479                                  ; 14/07/2013
  2480                                  ;kernel_init_err_msg:
  2481                                  ;	db 0Dh, 0Ah
  2482                                  ;	db 07h
  2483                                  ;	db 'Kernel initialization ERROR !'
  2484                                  ;	db 0Dh, 0Ah, 0 
  2485                                  ; 24/08/2015
  2486                                  ;;; (temporary kernel init message has been removed
  2487                                  ;;;  from 'sys_init' code)
  2488                                  ;kernel_init_ok_msg: 
  2489                                  ;	db 0Dh, 0Ah
  2490                                  ;	db 07h
  2491                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2492                                  ;	db 0Dh, 0Ah
  2493                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2494                                  ;	db 0Dh, 0Ah, 0
  2495                                  panic_msg:
  2496 00006981 0D0A07                  	db 0Dh, 0Ah, 07h
  2497 00006984 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2497 0000698D 726E656C2050616E69-
  2497 00006996 632021             
  2498 00006999 0D0A00                  	db 0Dh, 0Ah, 0
  2499                                  etc_init_err_msg:
  2500 0000699C 0D0A                    	db 0Dh, 0Ah
  2501 0000699E 07                      	db 07h
  2502 0000699F 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2502 000069A8 74632F696E69742021-
  2502 000069B1 3F                 
  2503 000069B2 0D0A00                  	db 0Dh, 0Ah, 0
  2504                                  
  2505                                  ; 10/05/2015
  2506                                  badsys_msg:
  2507 000069B5 0D0A                    	db 0Dh, 0Ah
  2508 000069B7 07                      	db 07h
  2509 000069B8 496E76616C69642053-     	db 'Invalid System Call !'
  2509 000069C1 797374656D2043616C-
  2509 000069CA 6C2021             
  2510 000069CD 0D0A                    	db 0Dh, 0Ah
  2511 000069CF 4541583A20              	db 'EAX: '
  2512                                  bsys_msg_eax:
  2513 000069D4 303030303030303068      	db '00000000h'
  2514 000069DD 0D0A                    	db 0Dh, 0Ah
  2515 000069DF 4549503A20              	db 'EIP: '
  2516                                  bsys_msg_eip:
  2517 000069E4 303030303030303068      	db '00000000h' 
  2518 000069ED 0D0A00                  	db 0Dh, 0Ah, 0
  2519                                  
  2520                                  BSYS_M_SIZE equ $ - badsys_msg
  2521                                  
  2522                                  
  2523                                  align 2
  2524                                  
  2525                                  ; EPOCH Variables
  2526                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2527                                  ; 09/04/2013 epoch variables
  2528                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2529                                  ;
  2530 000069F0 B207                    year: 	dw 1970
  2531                                  ;month: dw 1
  2532                                  ;day: 	dw 1
  2533                                  ;hour: 	dw 0
  2534                                  ;minute: dw 0
  2535                                  ;second: dw 0
  2536                                  ; 02/06/2022
  2537 000069F2 01                      month:	db 1
  2538 000069F3 01                      day:	db 1
  2539 000069F4 01                      hour:	db 1
  2540 000069F5 01                      minute: db 1
  2541 000069F6 01                      second:	db 1
  2542 000069F7 01                      	db 1
  2543                                  
  2544                                  DMonth:
  2545 000069F8 0000                    	dw 0
  2546 000069FA 1F00                    	dw 31
  2547 000069FC 3B00                    	dw 59
  2548 000069FE 5A00                    	dw 90
  2549 00006A00 7800                    	dw 120
  2550 00006A02 9700                    	dw 151
  2551 00006A04 B500                    	dw 181
  2552 00006A06 D400                    	dw 212
  2553 00006A08 F300                    	dw 243
  2554 00006A0A 1101                    	dw 273
  2555 00006A0C 3001                    	dw 304
  2556 00006A0E 4E01                    	dw 334
  2557                                  
  2558                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2559                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2560 00006A10 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2561                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2562 00006A12 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2563 00006A14 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2564                                  		   ;   between 16 MB and 4 GB.
  2565 00006A16 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2566                                  
  2567                                  ; 02/01/2022
  2568                                  KEND:
  2569                                  
  2570 00006A18 90<rep 8h>              align 16
  2571                                  
  2572                                  bss_start:
  2573                                  
  2574                                  ABSOLUTE bss_start
  2575                                  
  2576                                  	; 11/03/2015
  2577                                  	; Interrupt Descriptor Table (20/08/2014)
  2578                                  idt:
  2579 00006A20 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2580                                  idt_end:
  2581                                  
  2582                                  ;alignb 4
  2583                                  
  2584                                  task_state_segment:
  2585                                  	; 24/03/2015
  2586 00006C20 ????                    tss.link:   resw 1
  2587 00006C22 ????                    	    resw 1
  2588                                  ; tss offset 4	
  2589 00006C24 ????????                tss.esp0:   resd 1
  2590 00006C28 ????                    tss.ss0:    resw 1
  2591 00006C2A ????                    	    resw 1	
  2592 00006C2C ????????                tss.esp1:   resd 1
  2593 00006C30 ????                    tss.ss1:    resw 1
  2594 00006C32 ????                    	    resw 1 	
  2595 00006C34 ????????                tss.esp2:   resd 1
  2596 00006C38 ????                    tss.ss2:    resw 1
  2597 00006C3A ????                    	    resw 1
  2598                                  ; tss offset 28
  2599 00006C3C ????????                tss.CR3:    resd 1
  2600 00006C40 ????????                tss.eip:    resd 1
  2601 00006C44 ????????                tss.eflags: resd 1
  2602                                  ; tss offset 40
  2603 00006C48 ????????                tss.eax:    resd 1		 		
  2604 00006C4C ????????                tss.ecx:    resd 1
  2605 00006C50 ????????                tss.edx:    resd 1
  2606 00006C54 ????????                tss.ebx:    resd 1
  2607 00006C58 ????????                tss.esp:    resd 1
  2608 00006C5C ????????                tss.ebp:    resd 1
  2609 00006C60 ????????                tss.esi:    resd 1
  2610 00006C64 ????????                tss.edi:    resd 1
  2611                                  ; tss offset 72
  2612 00006C68 ????                    tss.ES:     resw 1
  2613 00006C6A ????                    	    resw 1	
  2614 00006C6C ????                    tss.CS:	    resw 1
  2615 00006C6E ????                    	    resw 1
  2616 00006C70 ????                    tss.SS:	    resw 1
  2617 00006C72 ????                    	    resw 1
  2618 00006C74 ????                    tss.DS:	    resw 1
  2619 00006C76 ????                    	    resw 1
  2620 00006C78 ????                    tss.FS:	    resw 1
  2621 00006C7A ????                    	    resw 1
  2622 00006C7C ????                    tss.GS:	    resw 1
  2623 00006C7E ????                    	    resw 1		
  2624 00006C80 ????                    tss.LDTR:   resw 1
  2625 00006C82 ????                    	    resw 1
  2626                                  ; tss offset 100		
  2627 00006C84 ????                    	    resw 1		
  2628 00006C86 ????                    tss.IOPB:   resw 1
  2629                                  ; tss offset 104 
  2630                                  tss_end:
  2631                                  
  2632 00006C88 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2633                                  		  ;   (Physical address = Virtual address)	 	
  2634 00006C8C ????????                memory_size: resd 1 ; memory size in pages
  2635 00006C90 ????????                free_pages:  resd 1 ; number of free pages		
  2636 00006C94 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2637                                  		  ;   first free page search
  2638 00006C98 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2639                                  		  ;   next free page search will be
  2640                                  		  ; stopped after it. (end of M.A.T.)
  2641 00006C9C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2642                                  		  ; first free page search
  2643                                  		  ;   will be started on it. (for user)
  2644 00006CA0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2645                                  
  2646                                  ;;;
  2647                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2648                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2649 00006CA4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2650                                  			  ; NOTE: active page only
  2651 00006CA6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2652                                  active_page: 
  2653 00006CB6 ??                      ptty: 	     resb 1 	  ; current tty
  2654                                  ; 01/07/2015
  2655 00006CB7 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2656                                  ; 26/10/2015
  2657                                  ; 07/09/2014
  2658 00006CB8 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2659                                  
  2660                                  ; 21/08/2014
  2661 00006CCC ????????                tcount:	     resd 1
  2662                                  
  2663                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2664 00006CD0 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2665                                  
  2666                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2667                                  ; (open mode locks for pseudo TTYs)
  2668                                  ; [ major tty locks (return error in any conflicts) ]
  2669 00006CD4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2670                                  
  2671                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2672                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2673 00006CE8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2674                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2675                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2676                                  ;; 0 means serial port is not available 
  2677                                  ;;comprm: ; 25/06/2014
  2678 00006CF2 ??                      com1p:       resb 1  ;;0E3h
  2679 00006CF3 ??                      com2p:       resb 1  ;;0E3h
  2680                                  
  2681                                  ; 17/11/2015
  2682                                  ; request for response (from the terminal)	
  2683 00006CF4 ????                    req_resp:     resw 1 			
  2684                                  ; 07/11/2015
  2685 00006CF6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2686                                  		    ; (0= COM1, 1= COM2)
  2687                                  ; 09/11/2015
  2688 00006CF7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2689                                  ; 07/11/2015
  2690 00006CF8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2691 00006CFA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2692                                  
  2693                                  ; 23/10/2015
  2694                                  ; SERIAL PORTS - COMMUNICATION MODES
  2695                                  ; (Retro UNIX 386 v1 feature only!)
  2696                                  ; 0 - command mode (default/initial mode)
  2697                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2698                                  ;;; communication modes for futre versions:  
  2699                                  ; // 2 - keyboard mode (ascii+scancode input)
  2700                                  ; // 3 - mouse mode
  2701                                  ; // 4 - device control (output) mode
  2702                                  ; VALID COMMANDS for current version:
  2703                                  ; 	'LOGIN'
  2704                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2705                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2706                                  ;  Login response: db 0FFh, 'login', 0
  2707                                  ;	 ("login request accepted, wait for login prompt") 
  2708                                  ; When a login requests is received and acknowledged (by
  2709                                  ; serial port interrupt handler (communication procedure),
  2710                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2711                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2712                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2713                                  ; 
  2714                                  ; 'sys connect' system call is used to change communication mode
  2715                                  ; except 'LOGIN' command which is used to start terminal mode
  2716                                  ; by using (COM port) terminal.
  2717                                  
  2718                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2719                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2720                                  ;com1mode:    resb 1 ; communication mode for COM1
  2721                                  ;com1com:     resb 1 ; communication command for COM1
  2722                                  ;com2mode:    resb 1 ; communication mode for COM1
  2723                                  ;com2com      resb 1 ; communication command for COM1
  2724                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2725                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2726                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2727                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2728                                  
  2729                                  ; 22/08/2014 (RTC)
  2730                                  ; (Packed BCD)
  2731 00006CFC ??                      time_seconds: resb 1
  2732 00006CFD ??                      time_minutes: resb 1
  2733 00006CFE ??                      time_hours:   resb 1
  2734 00006CFF ??                      date_wday:    resb 1
  2735 00006D00 ??                      date_day:     resb 1
  2736 00006D01 ??                      date_month:   resb 1			
  2737 00006D02 ??                      date_year:    resb 1
  2738 00006D03 ??                      date_century: resb 1
  2739                                  
  2740                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2741                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2742                              <1> ; Last Modification: 10/07/2015
  2743                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2744                              <1> ;
  2745                              <1> ; *****************************************************************************
  2746                              <1> 
  2747                              <1> alignb 2
  2748                              <1> 
  2749                              <1> ;----------------------------------------
  2750                              <1> ;	TIMER DATA AREA 		:
  2751                              <1> ;----------------------------------------
  2752                              <1> 
  2753                              <1> TIMER_LH:	; 16/02/205
  2754 00006D04 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2755 00006D06 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2756 00006D08 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2757                              <1> 
  2758                              <1> ;----------------------------------------
  2759                              <1> ;	DISKETTE DATA AREAS		:
  2760                              <1> ;----------------------------------------
  2761                              <1> 
  2762 00006D09 ??                  <1> SEEK_STATUS:	resb	1
  2763 00006D0A ??                  <1> MOTOR_STATUS:	resb	1
  2764 00006D0B ??                  <1> MOTOR_COUNT:	resb	1
  2765 00006D0C ??                  <1> DSKETTE_STATUS:	resb	1
  2766 00006D0D ??????????????      <1> NEC_STATUS:	resb	7
  2767                              <1> 
  2768                              <1> ;----------------------------------------
  2769                              <1> ;	ADDITIONAL MEDIA DATA		:
  2770                              <1> ;----------------------------------------
  2771                              <1> 
  2772 00006D14 ??                  <1> LASTRATE:	resb 	1
  2773 00006D15 ??                  <1> HF_STATUS:	resb 	1
  2774 00006D16 ??                  <1> HF_ERROR:	resb 	1
  2775 00006D17 ??                  <1> HF_INT_FLAG:	resb 	1
  2776 00006D18 ??                  <1> HF_CNTRL:	resb 	1
  2777 00006D19 ????????            <1> DSK_STATE:	resb 	4
  2778 00006D1D ????                <1> DSK_TRK:	resb 	2
  2779                              <1> 
  2780                              <1> ;----------------------------------------
  2781                              <1> ;	FIXED DISK DATA AREAS		:
  2782                              <1> ;----------------------------------------
  2783                              <1> 
  2784 00006D1F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2785 00006D20 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2786 00006D21 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2787                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2788                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2789                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2790                              <1> 
  2791 00006D22 ????                <1> alignb 4
  2792                              <1> 
  2793                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2794                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2795                              <1> HF_TBL_VEC: ; 22/12/2014	
  2796 00006D24 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2797 00006D28 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2798 00006D2C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2799 00006D30 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2800                              <1> 
  2801                              <1> ; 03/01/2015
  2802 00006D34 ??                  <1> LBAMode:     	resb	1
  2803                              <1> 
  2804                              <1> ; *****************************************************************************
  2741                                  
  2742                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2743                                  
  2744                                  ;alignb 2
  2745                                  
  2746                                  ; 02/01/2022
  2747                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2748                                  
  2749                                  ; 24/12/2021
  2750                                  ; (memory page swap parameters are disabled as temporary)
  2751                                  ;
  2752                                  ;; Memory (swap) Data (11/03/2015)
  2753                                  ; 09/03/2015
  2754                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2755                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2756                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2757                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2758                                  ;swpd_next:  resd 1 ; next free page block
  2759                                  ;swpd_last:  resd 1 ; last swap page block	
  2760                                  	
  2761 00006D35 ??????                  alignb 4
  2762                                  
  2763                                  ; 10/07/2015
  2764                                  ; 28/08/2014
  2765 00006D38 ????????                error_code:	resd 1
  2766                                  ; 29/08/2014
  2767 00006D3C ????????                FaultOffset: 	resd 1
  2768                                  ; 21/09/2015
  2769 00006D40 ????????                PF_Count:	resd 1	; total page fault count
  2770                                  		       	; (for debugging - page fault analyze)
  2771                                  		 	; 'page _fault_handler' (memory.inc)
  2772                                  			; 'sysgeterr' (u9.s)
  2773                                  ; 26/02/2022
  2774 00006D44 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2775                                  			;  for a system call in next retro unix 386 version)
  2776                                  			; -2 ticks per second-
  2777                                  ;; 21/08/2015
  2778                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2779                                  
  2780                                  ; 02/01/2022
  2781                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2782                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYSX.INC (ux.s)
  2783                              <1> ; Last Modification: 26/02/2022
  2784                              <1> ; ----------------------------------------------------------------------------
  2785                              <1> ; Retro UNIX 386 v1 Kernel - ux.s
  2786                              <1> ; Last Modification: 15/05/2022
  2787                              <1> ;
  2788                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2789                              <1> ; (Modified from 
  2790                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2791                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2792                              <1> ; ----------------------------------------------------------------------------
  2793                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2794                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2795                              <1> ; <Bell Laboratories (17/3/1972)>
  2796                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2797                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2798                              <1> ; ****************************************************************************
  2799                              <1> ; 04/12/2015
  2800                              <1> 
  2801                              <1> alignb 2
  2802                              <1> 
  2803                              <1> inode:
  2804                              <1> 	; 11/03/2013. 
  2805                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2806                              <1> 	;i.
  2807                              <1> 
  2808 00006D48 ????                <1> 	i.flgs:	 resw 1
  2809 00006D4A ??                  <1> 	i.nlks:	 resb 1
  2810 00006D4B ??                  <1> 	i.uid:	 resb 1
  2811 00006D4C ????                <1>         i.size:  resw 1 ; size
  2812 00006D4E <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2813 00006D5E ????????            <1> 	i.ctim:	 resd 1
  2814 00006D62 ????????            <1> 	i.mtim:	 resd 1
  2815 00006D66 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2816                              <1> 
  2817                              <1> I_SIZE	equ $ - inode 
  2818                              <1> 
  2819                              <1> process:
  2820                              <1> 	; 26/02/2022
  2821                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2822                              <1> 	; 06/05/2015
  2823                              <1> 	; 11/03/2013 - 05/02/2014
  2824                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2825                              <1> 	;p.
  2826                              <1> 	
  2827 00006D68 <res 20h>           <1>         p.pid:   resw nproc
  2828 00006D88 <res 20h>           <1>         p.ppid:  resw nproc
  2829                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2830 00006DA8 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2831                              <1> 	; 26/02/2022 (p.waitc is not used)
  2832                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2833 00006DB8 <res 10h>           <1> 	p.link:	 resb nproc
  2834 00006DC8 <res 10h>           <1> 	p.stat:	 resb nproc
  2835                              <1> 
  2836                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2837 00006DD8 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2838                              <1> 			    ; 'user' structure	
  2839                              <1> 
  2840                              <1> P_SIZE	equ $ - process
  2841                              <1> 
  2842                              <1> ; fsp table (original UNIX v1)
  2843                              <1> ;
  2844                              <1> ;Entry
  2845                              <1> ;          15                                      0
  2846                              <1> ;  1     |---|---------------------------------------|
  2847                              <1> ;        |r/w|       i-number of open file           |
  2848                              <1> ;        |---|---------------------------------------| 
  2849                              <1> ;        |               device number               |
  2850                              <1> ;        |-------------------------------------------|
  2851                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2852                              <1> ;        |-------------------------------------------| 
  2853                              <1> ;        |  flag that says    | number of processes  |
  2854                              <1> ;        |   file deleted     | that have file open  |
  2855                              <1> ;        |-------------------------------------------| 
  2856                              <1> ;  2     |                                           |
  2857                              <1> ;        |-------------------------------------------| 
  2858                              <1> ;        |                                           |
  2859                              <1> ;        |-------------------------------------------|
  2860                              <1> ;        |                                           |
  2861                              <1> ;        |-------------------------------------------|
  2862                              <1> ;        |                                           |
  2863                              <1> ;        |-------------------------------------------| 
  2864                              <1> ;  3     |                                           | 
  2865                              <1> ;        |                                           |  
  2866                              <1> ;
  2867                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2868                              <1> 
  2869                              <1> ; 15/04/2015
  2870 00006E18 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2871 0000700C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2872 0000702C ????                <1> ii:	 resw 1
  2873                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2874                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2875                              <1> ; 11/01/2022
  2876 0000702E ??                  <1> idev:	 resb 1
  2877 0000702F ??                  <1> cdev:	 resb 1
  2878                              <1> ; 18/05/2015
  2879                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2880                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2881                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2882                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2883                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2884                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2885                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2886                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2887                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2888                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2889                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2890 00007030 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2891                              <1> 	        ; as above, for physical drives numbers in following table
  2892 00007031 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2893                              <1> ; 15/04/2015
  2894 00007032 ??                  <1> active:	 resb 1 
  2895 00007033 ??                  <1> 	 resb 1 ; 09/06/2015
  2896 00007034 ????                <1> mnti:	 resw 1
  2897 00007036 ????                <1> mntp:	 resw 1 ; 15/05/2022 ; (parent dir inumber of [mnti])
  2898 00007038 ????                <1> mpid:	 resw 1
  2899 0000703A ????                <1> rootdir: resw 1
  2900                              <1> ; 14/02/2014
  2901                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2902                              <1> ;		      Single level run queue
  2903                              <1> ;		      (in order to solve sleep/wakeup lock)
  2904 0000703C ????                <1> runq:	 resw 1
  2905 0000703E ??                  <1> imod:	 resb 1
  2906 0000703F ??                  <1> smod:	 resb 1
  2907 00007040 ??                  <1> mmod:	 resb 1
  2908 00007041 ??                  <1> sysflg:	 resb 1
  2909                              <1> 
  2910 00007042 ????                <1> alignb 4
  2911                              <1> 
  2912                              <1> user:
  2913                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2914                              <1> 	; 04/12/2015 
  2915                              <1> 	; 18/10/2015
  2916                              <1> 	; 12/10/2015
  2917                              <1> 	; 21/09/2015
  2918                              <1> 	; 24/07/2015
  2919                              <1> 	; 16/06/2015
  2920                              <1> 	; 09/06/2015
  2921                              <1> 	; 11/05/2015
  2922                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2923                              <1> 	; 10/10/2013
  2924                              <1> 	; 11/03/2013. 
  2925                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2926                              <1> 	;u.
  2927                              <1> 
  2928 00007044 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2929 00007048 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2930 0000704C ????????            <1> 	u.r0:	  resd 1 ; eax
  2931 00007050 ????                <1> 	u.cdir:	  resw 1
  2932 00007052 <res Ah>            <1> 	u.fp:	  resb 10
  2933 0000705C ????????            <1> 	u.fofp:	  resd 1
  2934 00007060 ????????            <1> 	u.dirp:	  resd 1
  2935 00007064 ????????            <1> 	u.namep:  resd 1
  2936 00007068 ????????            <1> 	u.off:	  resd 1
  2937 0000706C ????????            <1> 	u.base:	  resd 1
  2938 00007070 ????????            <1> 	u.count:  resd 1
  2939 00007074 ????????            <1> 	u.nread:  resd 1
  2940 00007078 ????????            <1> 	u.break:  resd 1 ; break
  2941 0000707C ????                <1> 	u.ttyp:	  resw 1 
  2942 0000707E <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2943                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2944 0000708E ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2945 0000708F ??                  <1> 	u.pri:	  resb 1 ; 
  2946 00007090 ????                <1> 	u.intr:	  resw 1
  2947 00007092 ????                <1> 	u.quit:	  resw 1
  2948                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2949 00007094 ????                <1> 	u.ilgins: resw 1
  2950                              <1> 	;u.cdrv:  resw 1 ; cdev
  2951 00007096 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2952 00007097 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2953 00007098 ??                  <1> 	u.uid:	  resb 1 ; uid
  2954 00007099 ??                  <1> 	u.ruid:	  resb 1
  2955 0000709A ??                  <1> 	u.bsys:	  resb 1
  2956 0000709B ??                  <1> 	u.uno:	  resb 1
  2957 0000709C ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2958                              <1> 	; tty number (rtty, rcvt, wtty)
  2959 000070A0 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2960                              <1> 	; last error number
  2961 000070A1 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2962                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2963 000070A5 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2964 000070A9 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2965 000070AD ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2966 000070B1 ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2967                              <1> 	;u.pncount: resw 1 
  2968                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2969                              <1> 	;u.pnbase:  resd 1 
  2970                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2971                              <1> 			 ; 09/06/2015
  2972 000070B3 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2973 000070B4 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2974                              <1> 			 ; 24/07/2015 - 24/06/2015
  2975                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2976                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2977                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2978                              <1>  			 ; 24/06/2015	  	
  2979                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2980                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2981                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2982 000070B5 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2983                              <1> 
  2984 000070B9 ??????              <1> alignb 4
  2985                              <1> 
  2986                              <1> U_SIZE	equ $ - user
  2987                              <1> 
  2988                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2989 000070BC ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2990 000070C0 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2991 000070C4 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2992 000070C8 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2993                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  2994 000070CA ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2995 000070CB ??                  <1> 	resb 1 
  2996 000070CC ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2997                              <1> 
  2998                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2999                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3000 000070D0 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3001 000070D1 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3002 000070D2 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3003 000070D3 ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  3004                              <1> 
  3005                              <1> ;alignb 4
  3006                              <1> 
  3007                              <1> ; 22/08/2015
  3008 000070D4 <res C30h>          <1> buffer: resb nbuf * 520
  3009                              <1> 
  3010 00007D04 ????????????????    <1> sb0:	resd 2
  3011                              <1> ;s:
  3012                              <1> ; (root disk) super block buffer
  3013                              <1> systm:
  3014                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3015                              <1> 	; 11/03/2013. 
  3016                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3017                              <1> 	;s.
  3018                              <1> 
  3019 00007D0C ????                <1> 	resw 1
  3020 00007D0E <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3021 00007E76 ????                <1> 	resw 1
  3022 00007E78 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  3023                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  3024 00007E98 ????????            <1> 	s.time:	 resd 1
  3025 00007E9C ????????            <1> 	s.syst:	 resd 1
  3026 00007EA0 ????????            <1>         s.wait_: resd 1 ; wait
  3027 00007EA4 ????????            <1> 	s.idlet: resd 1
  3028 00007EA8 ????????            <1> 	s.chrgt: resd 1
  3029 00007EAC ????                <1> 	s.drerr: resw 1
  3030                              <1> 
  3031                              <1> S_SIZE	equ $ - systm
  3032                              <1> 
  3033 00007EAE <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3034                              <1> 
  3035 00007F0C ????????????????    <1> sb1:	resd 2
  3036                              <1> ; (mounted disk) super block buffer
  3037                              <1> mount:	
  3038 00007F14 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3039                              <1> 
  3040                              <1> ;/ ux -- unix
  3041                              <1> ;
  3042                              <1> ;systm:
  3043                              <1> ;
  3044                              <1> ;	.=.+2
  3045                              <1> ;	.=.+128.
  3046                              <1> ;	.=.+2
  3047                              <1> ;	.=.+64.
  3048                              <1> ;	s.time: .=.+4
  3049                              <1> ;	s.syst: .=.+4
  3050                              <1> ;	s.wait: .=.+4
  3051                              <1> ;	s.idlet:.=.+4
  3052                              <1> ;	s.chrgt:.=.+4
  3053                              <1> ;	s.drerr:.=.+2
  3054                              <1> ;inode:
  3055                              <1> ;	i.flgs: .=.+2
  3056                              <1> ;	i.nlks: .=.+1
  3057                              <1> ;	i.uid:  .=.+1
  3058                              <1> ;	i.size: .=.+2
  3059                              <1> ;	i.dskp: .=.+16.
  3060                              <1> ;	i.ctim: .=.+4
  3061                              <1> ;	i.mtim: .=.+4
  3062                              <1> ;	. = inode+32.
  3063                              <1> ;mount:	.=.+1024.
  3064                              <1> ;proc:
  3065                              <1> ;	p.pid:  .=.+[2*nproc]
  3066                              <1> ;	p.dska: .=.+[2*nproc]
  3067                              <1> ;	p.ppid: .=.+[2*nproc]
  3068                              <1> ;	p.break:.=.+[2*nproc]
  3069                              <1> ;	p.link: .=.+nproc
  3070                              <1> ;	p.stat: .=.+nproc
  3071                              <1> ;tty:
  3072                              <1> ;	. = .+[ntty*8.]
  3073                              <1> ;fsp:	.=.+[nfiles*8.]
  3074                              <1> ;bufp:	.=.+[nbuf*2]+6
  3075                              <1> ;sb0:	.=.+8
  3076                              <1> ;sb1:	.=.+8
  3077                              <1> ;swp:	.=.+8
  3078                              <1> ;ii:	.=.+2
  3079                              <1> ;idev:	.=.+2
  3080                              <1> ;cdev:	.=.+2
  3081                              <1> ;deverr: .=.+12.
  3082                              <1> ;active: .=.+2
  3083                              <1> ;rfap:	.=.+2
  3084                              <1> ;rkap:	.=.+2
  3085                              <1> ;tcap:	.=.+2
  3086                              <1> ;tcstate:.=.+2
  3087                              <1> ;tcerrc: .=.+2
  3088                              <1> ;mnti:	.=.+2
  3089                              <1> ;mntd:	.=.+2
  3090                              <1> ;mpid:	.=.+2
  3091                              <1> ;clockp: .=.+2
  3092                              <1> ;rootdir:.=.+2
  3093                              <1> ;toutt:	.=.+16.
  3094                              <1> ;touts: .=.+32.
  3095                              <1> ;runq:	.=.+6
  3096                              <1> ;
  3097                              <1> ;wlist:	.=.+40.
  3098                              <1> ;cc:	.=.+30.
  3099                              <1> ;cf:	.=.+31.
  3100                              <1> ;cl:	.=.+31.
  3101                              <1> ;clist:	.=.+510.
  3102                              <1> ;imod:	.=.+1
  3103                              <1> ;smod:	.=.+1
  3104                              <1> ;mmod:	.=.+1
  3105                              <1> ;uquant: .=.+1
  3106                              <1> ;sysflg: .=.+1
  3107                              <1> ;pptiflg:.=.+1
  3108                              <1> ;ttyoch: .=.+1
  3109                              <1> ; .even
  3110                              <1> ; .=.+100.; sstack:
  3111                              <1> ;buffer: .=.+[ntty*140.]
  3112                              <1> ;	.=.+[nbuf*520.]
  3113                              <1> ;
  3114                              <1> ; . = core-64.
  3115                              <1> ;user:
  3116                              <1> ;	u.sp:    .=.+2
  3117                              <1> ;	u.usp:   .=.+2
  3118                              <1> ;	u.r0:    .=.+2
  3119                              <1> ;	u.cdir:  .=.+2
  3120                              <1> ;	u.fp:    .=.+10.
  3121                              <1> ;	u.fofp:  .=.+2
  3122                              <1> ;	u.dirp:  .=.+2
  3123                              <1> ;	u.namep: .=.+2
  3124                              <1> ;	u.off:   .=.+2
  3125                              <1> ;	u.base:  .=.+2
  3126                              <1> ;	u.count: .=.+2
  3127                              <1> ;	u.nread: .=.+2
  3128                              <1> ;	u.break: .=.+2
  3129                              <1> ;	u.ttyp:  .=.+2
  3130                              <1> ;	u.dirbuf:.=.+10.
  3131                              <1> ;	u.pri:   .=.+2
  3132                              <1> ;	u.intr:  .=.+2
  3133                              <1> ;	u.quit:  .=.+2
  3134                              <1> ;	u.emt:   .=.+2
  3135                              <1> ;	u.ilgins:.=.+2
  3136                              <1> ;	u.cdev:  .=.+2
  3137                              <1> ;	u.uid:   .=.+1
  3138                              <1> ;	u.ruid:  .=.+1
  3139                              <1> ;	u.bsys:  .=.+1
  3140                              <1> ;	u.uno:   .=.+1
  3141                              <1> ;. = core
  2782                                  
  2783                                  ; 27/12/2021
  2784                                  ;buffer: resb (nbuf*520)
  2785                                  
  2786                                  bss_end:
  2787                                  
  2788                                  ; 02/01/2022
  2789                                  BSS_SIZE equ bss_end - bss_start
  2790                                  
  2791                                  ; 27/12/2013
  2792                                  _end:  ; end of kernel code (and read only data, just before bss)
