     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.22
     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: 16/07/2022 ] ; 2022 modification (previous: 12/7/2022)
    13                                  ;
    14                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    15                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    16                                  ; <Bell Laboratories (17/3/1972)>
    17                                  ; <Preliminary Release of UNIX Implementation Document>
    18                                  ;
    19                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    20                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    21                                  ;
    22                                  ; ****************************************************************************
    23                                  ; 14/07/2022 (v0.2.0.22)
    24                                  ; 12/07/2022 (v0.2.0.21)
    25                                  ; 15/05/2022 - 14/06/2022 (v0.2.0.20) 
    26                                  ; 04/02/2016 (v0.2.0.17) - 29/04/2022 (v0.2.0.18) - 09/05/2022 (v0.2.0.19)
    27                                  
    28                                  ; Assembler: NASM 2.15
    29                                  ;	nasm unix386.s -l unix386.lst -o unix386 -Z error.txt
    30                                  
    31                                  ; 24/12/2013
    32                                  
    33                                  ; Entering protected mode:
    34                                  ; Derived from 'simple_asm.txt' source code file and 
    35                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    36                                  ; (gregor.brunmar@home.se)
    37                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    38                                  ;
    39                                  
    40                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    41                                  ; by Michael Chourdakis (2009) 
    42                                  ; http://www.codeproject.com/Articles/45788/
    43                                  ; http://www.michaelchourdakis.com
    44                                  ;
    45                                  
    46                                  ; Global Descriptor Table:
    47                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    48                                  ; by Linus Torvalds (1991-1992)
    49                                  ;
    50                                  
    51                                  KLOAD	equ 10000h ; Kernel loading address
    52                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    53                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    54                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    55                                  ; 19/03/2015
    56                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    57                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    58                                  ; 24/03/2015
    59                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    60                                  ; 19/03/2015
    61                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    62                                  		     ; (at the end of the 1st 4MB)
    63                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    64                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    65                                  
    66                                  ; 27/12/2013
    67                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    68                                  
    69                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    70                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    71                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    72                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    73                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    74                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    75                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    76                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    77                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    78                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    79                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    80                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    81                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    82                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    83                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    84                                  ;----------------------------------------
    85                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    86                                  ;-----------------------------------------------------------------------------
    87                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    88                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    89                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    90                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    91                                  
    92                                  ; Memory Allocation Table Address
    93                                  ; 05/11/2014
    94                                  ; 31/10/2014
    95                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    96                                  					; the 1st 1 MB memory space.
    97                                  					; (This address must be aligned
    98                                  					;  on 128 KB boundary, if it will be
    99                                  					;  changed later.)
   100                                  					; ((lower 17 bits of 32 bit M.A.T.
   101                                  					;   address must be ZERO)).
   102                                  					; ((((Reason: 32 bit allocation 
   103                                  					;     instructions, dword steps)))
   104                                  					; (((byte >> 12 --> page >> 5)))  
   105                                  ;04/11/2014	
   106                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   107                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   108                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   109                                  ;
   110                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   111                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   112                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   113                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   114                                  
   115                                  ; 17/02/2015 (unix386.s)
   116                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   117                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   118                                  ;
   119                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   120                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   121                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   122                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   123                                  
   124                                  
   125                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   126                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   127                                  ;
   128                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   129                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   130                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   131                                  		      ; otherwise it is standard FDPT with physical values 	
   132                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   133                                  		      ; (obsolete for IDE/ATA drives)
   134                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   135                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   136                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   137                                  			; Bit 4 : Reserved. Always 0
   138                                  			; Bit 3 : Set to 1 if more than 8 heads
   139                                  			; Bit 2-0 : Reserved. Alsways 0
   140                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   141                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   142                                  
   143                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   144                                  ; (11 bytes long) will be used by diskette handler/bios
   145                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   146                                  
   147                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   148                                  
   149                                  [ORG 0] 
   150                                  	; 12/11/2014
   151                                  	; Save boot drive number (that is default root drive)
   152 00000000 8816[685D]              	mov	[boot_drv], dl ; physical drv number
   153                                  
   154                                  	; Determine installed memory
   155                                  	; 31/10/2014
   156                                  	;
   157 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   158 00000007 CD15                    	int	15h	   ; for large configurations
   159 00000009 7308                    	jnc	short chk_ms
   160 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   161 0000000D CD15                    	int	15h
   162                                  	;	   
   163                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   164                                  	;out	70h, al ; select CMOS register
   165                                  	;in	al, 71h ; read data (1 byte)
   166                                  	;mov	cl, al
   167                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   168                                  	;out	70h, al ; select CMOS register
   169                                  	;in	al, 71h ; read data (1 byte)
   170                                  	;mov	ch, al
   171                                   	;      
   172 0000000F 89C1                    	mov	cx, ax
   173 00000011 31D2                    	xor	dx, dx
   174                                  chk_ms:
   175 00000013 890E[D25F]              	mov	[mem_1m_1k], cx
   176 00000017 8916[D45F]              	mov	[mem_16m_64k], dx
   177                                  	; 05/11/2014
   178                                  	;and	dx, dx
   179                                  	;jz	short L2
   180 0000001B 81F90004                        cmp     cx, 1024
   181 0000001F 7351                    	jnb	short L0
   182                                  		 ; insufficient memory_error	
   183                                  		 ; Minimum 2 MB memory is needed... 
   184                                  	; 05/11/2014
   185                                  	; (real mode error printing)
   186 00000021 FB                      	sti
   187 00000022 BE[3600]                	mov	si, msg_out_of_memory
   188 00000025 BB0700                  	mov	bx, 7
   189 00000028 B40E                    	mov	ah, 0Eh	; write tty
   190                                  oom_1:
   191 0000002A AC                      	lodsb
   192 0000002B 08C0                    	or	al, al
   193 0000002D 7404                    	jz	short oom_2
   194 0000002F CD10                    	int	10h
   195 00000031 EBF7                    	jmp	short oom_1
   196                                  oom_2:
   197 00000033 F4                              hlt
   198 00000034 EBFD                    	jmp	short oom_2
   199                                  
   200                                  ; 04/02/2022
   201                                  ; 05/11/2014
   202                                  msg_out_of_memory:
   203 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   204 00000039 496E73756666696369-             db      'Insufficient memory !'
   204 00000042 656E74206D656D6F72-
   204 0000004B 792021             
   205 0000004E 0D0A                    	db	0Dh, 0Ah
   206                                  _int13h_48h_buffer: 
   207                                  	; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc')
   208 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   208 00000059 324D42206D656D6F72-
   208 00000062 79206973206E656564-
   208 0000006B 65642E29           
   209 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   210                                  
   211                                  L0:
   212                                  %include 'diskinit.inc' ; 07/03/2015
   213                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKINIT.INC
   214                              <1> ; Last Modification: 12/07/2022
   215                              <1> ; ************************************************************************
   216                              <1> ; Ref: Retro UNIX 386 v1.1 'diskinit.inc' modification: 12/07/2022
   217                              <1> 
   218                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   219                              <1> 
   220                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   221                              <1> 
   222                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18)
   223                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   224                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   225                              <1> ;L0:
   226                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   227                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   228 00000072 BA7F00              <1> 	mov	dx, 7Fh
   229                              <1> L1:	
   230 00000075 FEC2                <1> 	inc	dl
   231 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   232                              <1> 			; Phoenix EDD v1.1 - EDD v3
   233 00000079 BBAA55              <1> 	mov	bx, 55AAh
   234 0000007C CD13                <1> 	int 	13h
   235 0000007E 721A                <1> 	jc	short L2
   236                              <1> 
   237 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   238 00000084 7514                <1> 	jne	short L2
   239 00000086 FE06[6B5D]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   240 0000008A 8816[6A5D]          <1>         mov     [last_drv], dl  ; last hard disk number
   241 0000008E BB[EE5C]            <1> 	mov	bx, hd0_type - 80h
   242 00000091 01D3                <1> 	add	bx, dx	 
   243 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   244                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   245                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   246                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   247                              <1>                          ;            (EDD) ready (DPTE ready)
   248                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   249                              <1>                          ;            (EDD-3)
   250                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   251 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   252 00000098 72DB                <1> 	jb	short L1
   253                              <1> L2:
   254                              <1> 	; 23/11/2014
   255                              <1> 	; 19/11/2014
   256 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   257                              <1> 	; 04/02/2016 (esi -> si)
   258 0000009C BE[6C5D]            <1> 	mov	si, fd0_type
   259                              <1> L3:
   260                              <1> 	; 14/01/2015
   261 0000009F 8816[695D]          <1> 	mov	[drv], dl
   262                              <1> 	;
   263 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   264 000000A5 CD13                <1> 	int	13h	
   265 000000A7 7210                <1> 	jc	short L4
   266                              <1> 		; BL = drive type (for floppy drives)
   267                              <1> 		; DL = number of floppy drives
   268                              <1> 		;		
   269                              <1> 		; ES:DI = Address of DPT from BIOS
   270                              <1> 		;
   271 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   272                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   273                              <1> 	; 14/01/2015
   274 000000AB E8BB01              <1> 	call	set_disk_parms
   275                              <1> 	; 10/12/2014
   276 000000AE 81FE[6C5D]          <1> 	cmp	si, fd0_type
   277 000000B2 7705                <1> 	ja	short L4
   278 000000B4 46                  <1> 	inc	si ; fd1_type
   279 000000B5 B201                <1> 	mov	dl, 1
   280 000000B7 EBE6                <1> 	jmp	short L3
   281                              <1> L4:
   282                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   283 000000B9 B27F                <1> 	mov	dl, 7Fh
   284                              <1> 	; 24/12/2014 (Temporary)
   285 000000BB 803E[6B5D]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   286                              <1> 	;ja	L10       ; yes, all fixed disk operations
   287                              <1> 			  ; will be performed according to
   288                              <1> 			  ; present EDD specification
   289                              <1> 	; 02/01/2022
   290 000000C0 7603                <1> 	jna	short L5
   291 000000C2 E99100              <1> 	jmp	L10
   292                              <1> L5:
   293 000000C5 FEC2                <1> 	inc 	dl
   294 000000C7 8816[695D]          <1>         mov     [drv], dl
   295 000000CB 8816[6A5D]          <1>         mov     [last_drv], dl ; 14/01/2015
   296 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   297 000000D1 CD13                <1> 	int	13h	; (conventional function)
   298                              <1> 	;jc	L13	; fixed disk drive not ready
   299                              <1> 	; 02/01/2022
   300 000000D3 7303                <1> 	jnc	short L6
   301 000000D5 E98301              <1> 	jmp	L13
   302                              <1> L6:
   303 000000D8 8816[6B5D]          <1>         mov     [hdc], dl ; number of drives
   304                              <1> 	;; 14/01/2013
   305                              <1> 	;;push	cx
   306 000000DC E88A01              <1> 	call	set_disk_parms
   307                              <1> 	;;pop	cx
   308                              <1> 	;
   309                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   310 000000DF 8A16[695D]          <1>         mov     dl, [drv]
   311 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   312 000000E6 80FA80              <1> 	cmp	dl, 80h
   313 000000E9 7603                <1> 	jna	short L7
   314 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   315                              <1> L7:	
   316 000000EE 31C0                <1> 	xor	ax, ax
   317 000000F0 8ED8                <1> 	mov	ds, ax
   318 000000F2 8B37                <1>         mov     si, [bx]
   319 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   320 000000F7 8ED8                <1> 	mov	ds, ax
   321 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   322                              <1> 	;jne	L12 ; invalid FDPT
   323                              <1> 	; 02/01/2022
   324 000000FC 7403                <1> 	je	short L7_8
   325 000000FE E95601              <1> 	jmp	L12
   326                              <1> L7_8:
   327 00000101 BF0000              <1> 	mov	di, HD0_DPT
   328 00000104 80FA80              <1> 	cmp	dl, 80h
   329 00000107 7603                <1> 	jna	short L8
   330 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   331                              <1> L8:
   332                              <1> 	; 30/12/2014
   333 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   334 0000010F 8EC0                <1> 	mov	es, ax
   335                              <1> 	; 24/12/2014
   336 00000111 B90800              <1> 	mov	cx, 8
   337 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   338 00000116 8CC8                <1> 	mov	ax, cs
   339 00000118 8ED8                <1> 	mov	ds, ax
   340                              <1> 	; 02/02/2015
   341 0000011A 8A0E[695D]          <1>         mov     cl, [drv]
   342 0000011E 88CB                <1> 	mov	bl, cl
   343 00000120 B8F001              <1> 	mov	ax, 1F0h
   344 00000123 80E301              <1> 	and	bl, 1
   345 00000126 7406                <1> 	jz	short L9
   346 00000128 C0E304              <1> 	shl	bl, 4
   347 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   348                              <1> L9:
   349 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   350 0000012F 050602              <1> 	add	ax, 206h
   351 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   352 00000133 88D8                <1> 	mov	al, bl
   353 00000135 04A0                <1> 	add	al, 0A0h
   354 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   355                              <1> 	;
   356 00000138 FE06[695D]          <1> 	inc	byte [drv]
   357 0000013C BB[EE5C]            <1> 	mov	bx, hd0_type - 80h
   358 0000013F 01CB                <1> 	add	bx, cx
   359 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   360 00000144 A0[6B5D]            <1> 	mov	al, [hdc]
   361 00000147 FEC8                <1> 	dec	al
   362                              <1> 	;jz	L13
   363                              <1> 	; 02/01/2022
   364 00000149 7408                <1> 	jz	short L9_10
   365 0000014B 80FA80              <1> 	cmp	dl, 80h
   366                              <1>         ;jna	L5
   367                              <1> 	;jmp	L13
   368                              <1> 	; 02/01/2022
   369 0000014E 7703                <1> 	ja	short L9_10
   370 00000150 E972FF              <1> 	jmp	L5
   371                              <1> L9_10:
   372 00000153 E90501              <1>         jmp     L13
   373                              <1> L10:
   374 00000156 FEC2                <1> 	inc 	dl
   375                              <1> 	; 25/12/2014
   376 00000158 8816[695D]          <1> 	mov	[drv], dl
   377 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   378 0000015E CD13                <1> 	int	13h	; (conventional function)
   379                              <1> 	;jc	L13
   380                              <1> 	; 02/01/2022
   381 00000160 72F1                <1> 	jc	short L9_10
   382                              <1> 	; 14/01/2015
   383 00000162 8A16[695D]          <1> 	mov	dl, [drv]
   384 00000166 52                  <1> 	push	dx
   385 00000167 51                  <1> 	push	cx
   386 00000168 E8FE00              <1> 	call	set_disk_parms
   387 0000016B 59                  <1> 	pop	cx
   388 0000016C 5A                  <1> 	pop	dx
   389                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   390                              <1> 	; 04/02/2016 (esi -> si)
   391                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   392                              <1> 	;		 ; at the '_end' of kernel.
   393                              <1> 	;mov	word [si], 30
   394                              <1> 	; 06/07/2016
   395 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   396                              <1> 	; 09/07/2016
   397 00000170 B81E00              <1> 	mov	ax, 001Eh
   398 00000173 8824                <1> 	mov	[si], ah ; 0
   399 00000175 46                  <1> 	inc	si
   400 00000176 8904                <1> 	mov	word [si], ax
   401                              <1>  	; word [si] = 30
   402                              <1> 	;
   403 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   404 0000017A CD13                <1> 	int	13h
   405                              <1>         ;jc	L13
   406                              <1> 	; 02/01/2022
   407 0000017C 72D5                <1> 	jc	short L9_10
   408                              <1> 	; 04/02/2016 (ebx -> bx)
   409                              <1> 	; 14/01/2015
   410                              <1> 	;sub	bx, bx
   411 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   412 00000180 88D3                <1> 	mov	bl, dl
   413 00000182 80EB80              <1> 	sub	bl, 80h
   414 00000185 81C3[6E5D]          <1> 	add	bx, hd0_type
   415 00000189 8A07                <1> 	mov 	al, [bx]
   416 0000018B 0C80                <1> 	or	al, 80h
   417 0000018D 8807                <1> 	mov 	[bx], al	
   418 0000018F 81EB[6C5D]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   419 00000193 81C3[8E5D]          <1> 	add	bx, drv.status
   420 00000197 8807                <1> 	mov	[bx], al
   421                              <1> 	; 04/02/2016 (eax -> ax)
   422 00000199 8B4410              <1> 	mov	ax, [si+16]
   423 0000019C 854412              <1> 	test	ax, [si+18]
   424 0000019F 7413                <1> 	jz	short L10_A0h 
   425                              <1> 			; 'CHS only' disks on EDD system 
   426                              <1> 			;  are reported with ZERO disk size
   427 000001A1 81EB[8E5D]          <1> 	sub	bx, drv.status
   428 000001A5 C1E302              <1> 	shl	bx, 2
   429 000001A8 81C3[725D]          <1> 	add	bx, drv.size ; disk size (in sectors)
   430 000001AC 8907                <1> 	mov	[bx], ax
   431 000001AE 8B4412              <1> 	mov	ax, [si+18]
   432                              <1> 	;mov	[bx], ax
   433                              <1> 	; 02/01/2022 (BugFix)
   434 000001B1 894702              <1> 	mov	[bx+2], ax
   435                              <1> 
   436                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   437                              <1> 	 ; for CHS disks (28/02/2015)
   438                              <1> 	; 30/12/2014
   439 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   440 000001B7 88D0                <1> 	mov	al, dl
   441 000001B9 83E003              <1> 	and 	ax, 3
   442 000001BC C0E005              <1> 	shl	al, 5 ; *32
   443 000001BF 01C7                <1> 	add 	di, ax
   444 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   445 000001C4 8EC0                <1> 	mov	es, ax
   446                              <1> 	;
   447 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   448 000001C8 88CC                <1> 	mov	ah, cl	
   449 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   450 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   451 000001CE AB                  <1> 	stosw		
   452 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   453 000001D1 FEC0                <1> 	inc	al
   454 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   455 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   456 000001D6 AA                  <1> 	stosb
   457 000001D7 8A440C              <1> 	mov	al, [si+12]
   458 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   459 000001DB 31C0                <1>  	xor	ax, ax
   460                              <1> 	;dec	ax	 ; 02/01/2015 
   461 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   462                              <1> 	;xor	al, al	 ; 02/01/2015	
   463 000001DE AA                  <1> 	stosb		 ; reserved
   464 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   465                              <1> 		         ; (do not disable retries, 
   466                              <1> 			 ; more than 8 heads)
   467 000001E1 AA                  <1> 	stosb
   468 000001E2 8B4404              <1> 	mov	ax, [si+4]
   469 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   470                              <1> 	;push	ax	 ; 02/01/2015
   471 000001E6 8A4408              <1> 	mov	al, [si+8]
   472 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   473 000001EA 29C0                <1> 	sub 	ax, ax
   474                              <1> 	;pop	ax	 ; 02/01/2015	
   475 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   476 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   477 000001EF 243F                <1> 	and 	al, 3Fh	
   478 000001F1 AA                  <1> 	stosb
   479                              <1> 	;sub	al, al	 ; checksum
   480                              <1> 	;stosb
   481                              <1> 	;
   482 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   483 000001F5 AD                  <1> 	lodsw
   484 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   485 000001F7 AD                  <1> 	lodsw
   486 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   487                              <1> 	;
   488                              <1> 	; checksum calculation
   489 000001F9 89FE                <1> 	mov	si, di
   490 000001FB 06                  <1> 	push	es
   491 000001FC 1F                  <1> 	pop	ds
   492                              <1> 	;mov	cx, 16
   493 000001FD B90F00              <1> 	mov 	cx, 15
   494 00000200 29CE                <1> 	sub	si, cx
   495 00000202 30E4                <1> 	xor	ah, ah
   496                              <1> 	;del	cl
   497                              <1> L11:		
   498 00000204 AC                  <1> 	lodsb
   499 00000205 00C4                <1> 	add	ah, al
   500 00000207 E2FB                <1> 	loop	L11
   501                              <1> 	;
   502 00000209 88E0                <1> 	mov	al, ah
   503 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   504 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   505                              <1> 	;
   506 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   507 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   508                              <1> 	;
   509                              <1> 	; 23/02/2015
   510 00000210 57                  <1> 	push	di
   511                              <1> 	; ES:DI points to DPTE (FDPTE) location
   512                              <1> 	;mov	cx, 8
   513 00000211 B108                <1> 	mov	cl, 8
   514 00000213 F3A5                <1> 	rep	movsw	
   515                              <1> 	;
   516                              <1> 	; 23/02/2015
   517                              <1> 	; (P)ATA drive and LBA validation
   518                              <1> 	; (invalidating SATA drives and setting
   519                              <1> 	; CHS type I/O for old type fixed disks)
   520 00000215 5B                  <1> 	pop	bx
   521 00000216 8CC8                <1> 	mov	ax, cs
   522 00000218 8ED8                <1> 	mov	ds, ax
   523 0000021A 268B07              <1> 	mov	ax, [es:bx]
   524 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   525 00000220 7418                <1> 	je	short L11a
   526 00000222 3D7001              <1> 	cmp	ax, 170h
   527 00000225 7413                <1> 	je	short L11a
   528                              <1> 	; invalidation 
   529                              <1> 	; (because base port address is not 1F0h or 170h)
   530 00000227 30FF                <1> 	xor	bh, bh
   531 00000229 88D3                <1> 	mov	bl, dl
   532 0000022B 80EB80              <1> 	sub	bl, 80h
   533 0000022E C687[6E5D]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   534 00000233 808F[905D]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   535 00000238 EB14                <1> 	jmp	short L11b
   536                              <1> L11a:	
   537                              <1> 	; LBA validation
   538 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   539 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   540 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   541                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   542 00000242 28FF                <1> 	sub	bh, bh
   543 00000244 88D3                <1> 	mov	bl, dl
   544 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   545 00000249 80A7[905D]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   546                              <1> 				; bit 0 = LBA ready bit
   547                              <1> 	; 'diskio' procedure will check this bit !
   548                              <1> L11b:
   549 0000024E 3A16[6A5D]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   550 00000252 7307                <1>         jnb     short L13
   551 00000254 E9FFFE              <1>         jmp     L10
   552                              <1> L12:
   553                              <1> 	; Restore data registers
   554 00000257 8CC8                <1> 	mov	ax, cs
   555 00000259 8ED8                <1> 	mov	ds, ax	
   556                              <1> L13:
   557                              <1> 	; 13/12/2014
   558 0000025B 0E                  <1> 	push	cs
   559 0000025C 07                  <1> 	pop	es
   560                              <1> L14:
   561 0000025D B411                <1> 	mov 	ah, 11h
   562 0000025F CD16                <1> 	int 	16h
   563                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   564                              <1> 	; 02/01/2022
   565 00000261 7447                <1> 	jz	short L16
   566 00000263 B010                <1> 	mov	al, 10h
   567 00000265 CD16                <1> 	int 	16h
   568 00000267 EBF4                <1> 	jmp 	short L14
   569                              <1> L15:
   570                              <1> 
   571                              <1> ; //////
   572                              <1> 
   573                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   574                              <1> %if 0
   575                              <1> 	; 24/11/2014
   576                              <1> 	; 19/11/2014
   577                              <1> 	; 14/11/2014
   578                              <1> 	; Temporary code for disk searching code check
   579                              <1> 	;
   580                              <1> 	; This code will show existing (usable) drives and also
   581                              <1> 	; will show EDD interface support status for hard disks		
   582                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   583                              <1> 	; no need to get it again in protected mode...) 
   584                              <1> 	;	
   585                              <1> 	; 13/11/2014
   586                              <1> 	mov	bx, 7
   587                              <1> 	mov	ah, 0Eh
   588                              <1> 	mov	al, [fd0_type]
   589                              <1> 	and	al, al
   590                              <1> 	jz	short L15a
   591                              <1> 	mov	dl, al
   592                              <1> 	mov	al, 'F'
   593                              <1> 	int 	10h
   594                              <1> 	mov	al, 'D'
   595                              <1> 	int 	10h
   596                              <1> 	mov	al, '0'
   597                              <1> 	int 	10h
   598                              <1> 	mov	al, ' '
   599                              <1> 	int	10h
   600                              <1> 	call	L15c
   601                              <1> 	mov	al, ' '
   602                              <1> 	int	10h
   603                              <1> 	;
   604                              <1> 	mov	al, [fd1_type]
   605                              <1> 	and	al, al
   606                              <1> 	jz	short L15a
   607                              <1> 	mov	dl, al
   608                              <1> 	mov	al, 'F'
   609                              <1> 	int 	10h
   610                              <1> 	mov	al, 'D'
   611                              <1> 	int 	10h
   612                              <1> 	mov	al, '1'
   613                              <1> 	int 	10h
   614                              <1> 	mov	al, ' '
   615                              <1> 	int	10h
   616                              <1> 	call	L15c
   617                              <1> 	mov	al, ' '
   618                              <1> 	int	10h
   619                              <1> 	mov	al, ' '
   620                              <1> 	int	10h
   621                              <1> L15a:
   622                              <1> 	mov	al, [hd0_type]
   623                              <1> 	and	al, al
   624                              <1> 	jz	short L15b
   625                              <1> 	mov	dl, al
   626                              <1> 	mov	al, 'H'
   627                              <1> 	int 	10h
   628                              <1> 	mov	al, 'D'
   629                              <1> 	int 	10h
   630                              <1> 	mov	al, '0'
   631                              <1> 	int 	10h
   632                              <1> 	mov	al, ' '
   633                              <1> 	int 	10h
   634                              <1> 	call	L15c
   635                              <1> 	mov	al, ' '
   636                              <1> 	int	10h
   637                              <1> 	;
   638                              <1> 	mov	al, [hd1_type]
   639                              <1> 	and	al, al
   640                              <1> 	jz	short L15b
   641                              <1> 	mov	dl, al
   642                              <1> 	mov	al, 'H'
   643                              <1> 	int 	10h
   644                              <1> 	mov	al, 'D'
   645                              <1> 	int 	10h
   646                              <1> 	mov	al, '1'
   647                              <1> 	int 	10h
   648                              <1> 	mov	al, ' '
   649                              <1> 	int 	10h
   650                              <1> 	call	L15c
   651                              <1> 	mov	al, ' '
   652                              <1> 	int	10h
   653                              <1> 	;
   654                              <1> 	mov	al, [hd2_type]
   655                              <1> 	and	al, al
   656                              <1> 	jz	short L15b
   657                              <1> 	mov	dl, al
   658                              <1> 	mov	al, 'H'
   659                              <1> 	int 	10h
   660                              <1> 	mov	al, 'D'
   661                              <1> 	int 	10h
   662                              <1> 	mov	al, '2'
   663                              <1> 	int 	10h
   664                              <1> 	mov	al, ' '
   665                              <1> 	int 	10h
   666                              <1> 	call	L15c
   667                              <1> 	mov	al, ' '
   668                              <1> 	int	10h
   669                              <1> 	;
   670                              <1> 	mov	al, [hd3_type]
   671                              <1> 	and	al, al
   672                              <1> 	jz	short L15b
   673                              <1> 	mov	dl, al
   674                              <1> 	mov	al, 'H'
   675                              <1> 	int 	10h
   676                              <1> 	mov	al, 'D'
   677                              <1> 	int 	10h
   678                              <1> 	mov	al, '3'
   679                              <1> 	int 	10h
   680                              <1> 	mov	al, ' '
   681                              <1> 	int 	10h
   682                              <1> 	call	L15c
   683                              <1> 	mov	al, ' '
   684                              <1> 	int	10h
   685                              <1> 	;
   686                              <1> L15b:
   687                              <1> 	mov	al, 0Dh
   688                              <1> 	int 	10h	
   689                              <1> 	mov	al, 0Ah
   690                              <1> 	int 	10h
   691                              <1> 	;;xor	ah, ah
   692                              <1> 	;;int 	16h	
   693                              <1> 	;
   694                              <1>         ;jmp	L16  ; jmp short L16
   695                              <1>         ; 02/01/2022
   696                              <1> 	jmp	short L16
   697                              <1> 	;
   698                              <1> L15c:
   699                              <1> 	mov	dh, dl
   700                              <1> 	shr	dh, 4
   701                              <1> 	add	dh, 30h
   702                              <1> 	and	dl, 15
   703                              <1> 	add	dl, 30h
   704                              <1> 	mov	al, dh
   705                              <1> 	int	10h
   706                              <1> 	mov	al, dl
   707                              <1> 	int	10h
   708                              <1> 	retn
   709                              <1> 	;
   710                              <1> 	; end of temporary code for disk searching code check
   711                              <1> 
   712                              <1> %endif
   713                              <1> 
   714                              <1> ; //////
   715                              <1> 
   716                              <1> set_disk_parms:
   717                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
   718                              <1> 	; 09/05/2022
   719                              <1> 	;	disksize = cylinders*spt*heads (*)
   720                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   721                              <1> 	;
   722                              <1> 	; 04/02/2016 (ebx -> bx)
   723                              <1> 	; 10/07/2015
   724                              <1> 	; 14/01/2015
   725                              <1> 	;push	bx
   726 00000269 28FF                <1> 	sub	bh, bh
   727 0000026B 8A1E[695D]          <1> 	mov	bl, [drv]
   728 0000026F 80FB80              <1> 	cmp	bl, 80h
   729 00000272 7203                <1> 	jb	short sdp0
   730 00000274 80EB7E              <1> 	sub	bl, 7Eh
   731                              <1> sdp0:	
   732 00000277 81C3[8E5D]          <1> 	add	bx, drv.status
   733 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   734                              <1> 	;
   735 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   736 00000280 88CC                <1> 	mov	ah, cl ; 
   737 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   738 00000285 81EB[8E5D]          <1> 	sub	bx, drv.status
   739 00000289 D0E3                <1> 	shl	bl, 1
   740                              <1> 	; 12/07/2022
   741                              <1> 	;add	bx, drv.cylinders
   742 0000028B 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   743                              <1> 	;mov	[bx], ax
   744 0000028C 50                  <1> 	push	ax ; ** cylinders
   745                              <1> 	;sub	bx, drv.cylinders
   746                              <1> 	;add	bx, drv.heads
   747 0000028D 30E4                <1> 	xor	ah, ah
   748 0000028F 88F0                <1> 	mov	al, dh ; heads
   749 00000291 40                  <1> 	inc	ax
   750                              <1> 	;mov	[bx], ax
   751                              <1>         ;sub	bx, drv.heads
   752                              <1>         ;add	bx, drv.spt
   753 00000292 30ED                <1> 	xor	ch, ch
   754 00000294 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   755                              <1> 	;mov	[bx], cx
   756                              <1>         ;sub	bx, drv.spt
   757 00000297 D1E3                <1> 	shl	bx, 1
   758 00000299 81C3[725D]          <1> 	add	bx, drv.size ; disk size (in sectors)
   759                              <1> 	; LBA size = cylinders * heads * secpertrack
   760 0000029D F7E1                <1> 	mul	cx 
   761 0000029F 89C2                <1> 	mov	dx, ax	; heads*spt					
   762 000002A1 58                  <1> 	pop	ax ; ** cylinders
   763                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   764                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   765 000002A2 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   766 000002A4 8907                <1> 	mov	[bx], ax
   767 000002A6 895702              <1> 	mov	[bx+2], dx
   768                              <1> 	;
   769                              <1> 	;pop	bx
   770 000002A9 C3                  <1> 	retn
   771                              <1> 
   772                              <1> ;align 2
   773                              <1> 
   774                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   775                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   776                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   777                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   778                              <1> 
   779                              <1> ;last_drv:
   780                              <1> ;	db  0
   781                              <1> ;drv_status:
   782                              <1> ;	db  0,0,0,0,0,0
   783                              <1> ;	db 0
   784                              <1> 
   785                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   786                              <1> 
   787                              <1> L16:
   213                                  
   214                                  	; 10/11/2014
   215 000002AA FA                           	cli	; Disable interrupts (clear interrupt flag)
   216                                  		; Reset Interrupt MASK Registers (Master&Slave)
   217                                  	;mov	al, 0FFh	; mask off all interrupts
   218                                  	;out	21h, al		; on master PIC (8259)
   219                                  	;jmp 	$+2  ; (delay)
   220                                  	;out	0A1h, al	; on slave PIC (8259)
   221                                  	;
   222                                  	; Disable NMI 
   223 000002AB B080                    	mov   	al, 80h 
   224 000002AD E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   225                                  	; 23/02/2015
   226 000002AF 90                      	nop			;
   227                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   228                                  				; for preventing unknown state (!?)
   229                                  	;
   230                                   	; 20/08/2014
   231                                  	; Moving the kernel 64 KB back (to physical address 0)
   232                                  	; DS = CS = 1000h
   233                                  	; 05/11/2014
   234 000002B0 31C0                    	xor	ax, ax
   235 000002B2 8EC0                    	mov	es, ax ; ES = 0
   236                                  	;
   237 000002B4 B90040                  	mov	cx, (KEND - KLOAD)/4
   238 000002B7 31F6                    	xor	si, si
   239 000002B9 31FF                    	xor	di, di
   240 000002BB F366A5                  	rep	movsd
   241                                  	;
   242 000002BE 06                      	push	es ; 0
   243 000002BF 68[C302]                	push	L17
   244 000002C2 CB                      	retf
   245                                  	;
   246                                  L17:
   247                                  	; Turn off the floppy drive motor
   248 000002C3 BAF203                          mov     dx, 3F2h
   249 000002C6 EE                              out     dx, al ; 0 ; 31/12/2013
   250                                  
   251                                  	; Enable access to memory above one megabyte
   252                                  L18:
   253 000002C7 E464                    	in	al, 64h
   254 000002C9 A802                    	test	al, 2
   255 000002CB 75FA                            jnz     short L18
   256 000002CD B0D1                    	mov	al, 0D1h	; Write output port
   257 000002CF E664                    	out	64h, al
   258                                  L19:
   259 000002D1 E464                    	in	al, 64h
   260 000002D3 A802                    	test	al, 2
   261 000002D5 75FA                            jnz     short L19
   262 000002D7 B0DF                    	mov	al, 0DFh	; Enable A20 line
   263 000002D9 E660                    	out	60h, al
   264                                  ;L20:
   265                                  	;
   266                                  	; Load global descriptor table register
   267                                  
   268                                          ;mov     ax, cs
   269                                          ;mov     ds, ax
   270                                  
   271 000002DB 2E0F0116[905A]                  lgdt    [cs:gdtd]
   272                                  
   273 000002E1 0F20C0                          mov     eax, cr0
   274                                  	; or 	eax, 1
   275 000002E4 40                      	inc     ax
   276 000002E5 0F22C0                  	mov     cr0, eax
   277                                  
   278                                  	; Jump to 32 bit code
   279                                  	
   280 000002E8 66                      	db 66h 			; Prefix for 32-bit
   281 000002E9 EA                      	db 0EAh 		; Opcode for far jump
   282 000002EA [F0020000]              	dd StartPM 		; Offset to start, 32-bit
   283                                  				; (1000h:StartPM = StartPM + 10000h)
   284 000002EE 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   285                                  				; assuming that StartPM resides in code32
   286                                  
   287                                  [BITS 32] 
   288                                  
   289                                  StartPM:
   290                                  	; Kernel Base Address = 0 ; 30/12/2013
   291 000002F0 66B81000                	mov ax, KDATA           ; Save data segment identifier
   292 000002F4 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   293 000002F6 8EC0                           	mov es, ax              ; Move data segment into ES register
   294 000002F8 8EE0                           	mov fs, ax              ; Move data segment into FS register
   295 000002FA 8EE8                          	mov gs, ax              ; Move data segment into GS register
   296 000002FC 8ED0                            mov ss, ax              ; Move data segment into SS register
   297 000002FE BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   298                                  
   299                                  clear_bss: ; Clear uninitialized data area
   300                                  	; 11/03/2015
   301 00000303 31C0                    	xor	eax, eax ; 0
   302                                  	;mov	ecx, (bss_end - bss_start)/4
   303                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   304                                  	; 27/02/2022
   305 00000305 B9C0060000              	mov	ecx, BSS_SIZE/4
   306 0000030A BF[E05F0000]            	mov	edi, bss_start
   307 0000030F F3AB                    	rep	stosd  	
   308                                  
   309                                  memory_init:
   310                                  	; Initialize memory allocation table and page tables
   311                                  	; 16/11/2014
   312                                  	; 15/11/2014
   313                                  	; 07/11/2014
   314                                  	; 06/11/2014
   315                                  	; 05/11/2014
   316                                  	; 04/11/2014
   317                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   318                                  	;
   319                                  ;	xor	eax, eax
   320                                  ;	xor 	ecx, ecx
   321 00000311 B108                    	mov	cl, 8
   322 00000313 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   323 00000318 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   324                                  				   ; for the first 1 MB memory
   325                                  	;
   326 0000031A 668B0D[D25F0000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   327                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   328 00000321 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   329 00000325 890D[50620000]          	mov	[free_pages], ecx
   330 0000032B 668B15[D45F0000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   331                                  				   ; between 16 MB and 4 GB.	
   332 00000332 6609D2                  	or	dx, dx
   333 00000335 7413                    	jz	short mi_0
   334                                  	;
   335 00000337 6689D0                  	mov	ax, dx
   336 0000033A C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   337 0000033D 0105[50620000]          	add	[free_pages], eax
   338 00000343 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   339 00000348 EB07                    	jmp	short mi_1
   340                                  mi_0:
   341 0000034A 6689C8                  	mov	ax, cx
   342 0000034D 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   343                                  mi_1:
   344 00000351 A3[4C620000]            	mov	[memory_size], eax ; Total available memory in pages
   345                                  				   ; 1 alloc. tbl. bit = 1 memory page
   346                                  				   ; 32 allocation bits = 32 mem. pages   
   347                                  	;
   348 00000356 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   349 0000035B C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   350                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   351                                  				   ;  --> x M.A.T. pages, if y = 0
   352 0000035E 66A3[60620000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   353 00000364 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   354                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   355 00000367 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   356                                  	; Set/Calculate Kernel's Page Directory Address
   357 00000369 81C300001000            	add	ebx, MEM_ALLOC_TBL
   358 0000036F 891D[48620000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   359                                  				   ; just after the last M.A.T. page
   360                                  	;
   361 00000375 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   362 00000378 A3[58620000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   363                                  	;			   ; (allocation status search must be 
   364                                  				   ; stopped after here)	
   365 0000037D 31C0                    	xor	eax, eax
   366 0000037F 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   367 00000380 6651                    	push	cx
   368 00000382 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   369                                  				   ; count of 32 allocation bits
   370 00000385 F3AB                    	rep	stosd
   371 00000387 6659                    	pop	cx
   372 00000389 40                      	inc	eax		   ; 0	
   373 0000038A 80E11F                  	and	cl, 31		   ; remain bits
   374 0000038D 7412                    	jz	short mi_4
   375 0000038F 8907                    	mov	[edi], eax	   ; reset	
   376                                  mi_2:
   377 00000391 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   378 00000394 FEC9                    	dec	cl
   379 00000396 7404                    	jz	short mi_3
   380 00000398 FEC0                    	inc	al
   381 0000039A EBF5                    	jmp	short mi_2
   382                                  mi_3:
   383 0000039C 28C0                    	sub	al, al	   	   ; 0
   384 0000039E 83C704                  	add	edi, 4		   ; 15/11/2014
   385                                  mi_4:
   386 000003A1 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   387 000003A4 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   388                                  	;	
   389 000003A6 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   390                                  	;	
   391 000003AB 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   392 000003AD 7406                    	jz	short mi_5	  ; jump if EDI points to 
   393                                  				  ;         end of first 16 MB	
   394 000003AF D1E9                    	shr	ecx, 1		  ; convert to dword count
   395 000003B1 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   396 000003B3 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   397                                  				  ; (memory hole under 16 MB)
   398                                  mi_5:
   399 000003B5 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   400 000003B8 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   401 000003BA 9C                      	pushf			  ; 16/11/2014		
   402 000003BB 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   403 000003BC F3AB                    	rep	stosd
   404 000003BE 40                      	inc	eax		  ; 0
   405 000003BF 9D                      	popf			  ; 16/11/2014
   406 000003C0 7305                    	jnc	short mi_6
   407 000003C2 6648                    	dec	ax		  ; eax = 0000FFFFh
   408 000003C4 AB                      	stosd
   409 000003C5 6640                    	inc	ax		  ; 0		
   410                                  mi_6:
   411 000003C7 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   412 000003C9 730A                    	jnb	short mi_7	  ; end of memory allocation table
   413                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   414 000003CB 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   415 000003CD 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   416 000003CF D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   417 000003D1 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   418 000003D3 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   419                                  mi_7:
   420                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   421 000003D5 BA00001000              	mov	edx, MEM_ALLOC_TBL
   422                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   423                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   424 000003DA 668B0D[60620000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   425 000003E1 89D7                    	mov	edi, edx
   426 000003E3 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   427                                  				  ; byte offset in M.A.T.
   428                                  				  ; (1 M.A.T. byte points to 
   429                                  				  ;	      32768 bytes)
   430                                  				  ; Note: MEM_ALLOC_TBL address 
   431                                  				  ; must be aligned on 128 KB 
   432                                  				  ; boundary!
   433 000003E6 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   434                                  	; eax = 0
   435 000003E8 290D[50620000]          	sub	[free_pages], ecx ; 07/11/2014
   436                                  mi_8:
   437 000003EE 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   438                                  	;dec	bl
   439 000003F1 FEC9                    	dec	cl
   440 000003F3 7404                    	jz	short mi_9
   441 000003F5 FEC0                    	inc	al
   442 000003F7 EBF5                    	jmp	short mi_8
   443                                  mi_9:
   444                                  	;
   445                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   446                                  	;		(allocate pages for system page tables)
   447                                  
   448                                  	; edx = MEM_ALLOC_TBL
   449 000003F9 8B0D[4C620000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   450 000003FF 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   451 00000405 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   452                                  				 ; page table count (PDE count)
   453                                  	;
   454 00000408 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   455                                  	;
   456 00000409 41                      	inc	ecx		 ; +1 for kernel page directory	
   457                                  	;
   458 0000040A 290D[50620000]          	sub	[free_pages], ecx ; 07/11/2014
   459                                  	;
   460 00000410 8B35[48620000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   461 00000416 C1EE0C                  	shr	esi, 12		 ; convert to page number
   462                                  mi_10:
   463 00000419 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   464 0000041B 89C3                    	mov	ebx, eax
   465 0000041D C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   466 00000420 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   467                                  				 ;   to align on dword boundary
   468 00000423 83E01F                  	and	eax, 31		 ; set allocation bit position 
   469                                  				 ;  (bit 0 to bit 31)
   470                                  	;
   471 00000426 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   472                                  	;
   473 00000428 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   474                                  	;
   475 0000042B 46                      	inc	esi		 ; next page table
   476 0000042C E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   477                                  				 ; (ecx = page table count + 1)		
   478                                  	;
   479 0000042E 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   480                                  	;
   481                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   482                                  	;
   483                                  	; Initialize Kernel's Page Directory
   484 0000042F 8B3D[48620000]          	mov	edi, [k_page_dir]
   485 00000435 89F8                    	mov	eax, edi
   486 00000437 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   487                                  		     	      ; supervisor + read&write + present
   488 00000439 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   489                                  mi_11:
   490 0000043B 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   491                                  			        ; EAX points to next page table
   492 00000440 AB                      	stosd
   493 00000441 E2F8                    	loop	mi_11
   494 00000443 29C0                    	sub	eax, eax	; Empty PDE
   495 00000445 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   496 00000449 29D1                    	sub	ecx, edx
   497 0000044B 7402                    	jz	short mi_12
   498 0000044D F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   499                                  	;
   500                                  	; Initialization of Kernel's Page Directory is OK, here.
   501                                  mi_12:
   502                                  	; Initialize Kernel's Page Tables
   503                                  	;
   504                                  	; (EDI points to address of page table 0)
   505                                  	; eax = 0
   506 0000044F 8B0D[4C620000]          	mov	ecx, [memory_size] ; memory size in pages
   507 00000455 89CA                    	mov	edx, ecx	; (***)
   508 00000457 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   509                                  			     ; supervisor + read&write + present 	
   510                                  mi_13:
   511 00000459 AB                      	stosd
   512 0000045A 0500100000              	add	eax, 4096	
   513 0000045F E2F8                    	loop	mi_13	
   514 00000461 6681E2FF03              	and	dx, 1023	; (***)
   515 00000466 740B                    	jz	short mi_14
   516 00000468 66B90004                	mov	cx, 1024	
   517 0000046C 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   518 0000046F 31C0                    	xor	eax, eax
   519 00000471 F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   520                                  				; of the last page table
   521                                  mi_14:
   522                                  	;  Initialization of Kernel's Page Tables is OK, here.
   523                                  	;
   524 00000473 89F8                    	mov	eax, edi	; end of the last page table page
   525                                  			        ; (beginging of user space pages)
   526 00000475 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   527 00000478 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   528                                  				; aligning on dword boundary	
   529                                  	 
   530 0000047A A3[5C620000]            	mov	[first_page], eax
   531 0000047F A3[54620000]            	mov	[next_page], eax ; The first free page pointer
   532                                  				 ; for user programs
   533                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   534                                  	;
   535                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   536                                  	;
   537                                  	
   538                                  	; Enable paging
   539                                  	;
   540 00000484 A1[48620000]                    mov     eax, [k_page_dir]
   541 00000489 0F22D8                  	mov	cr3, eax
   542 0000048C 0F20C0                  	mov	eax, cr0
   543 0000048F 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   544 00000494 0F22C0                  	mov	cr0, eax
   545                                          ;jmp    KCODE:StartPMP
   546                                  
   547 00000497 EA                      	db 0EAh 		; Opcode for far jump
   548 00000498 [9E040000]                      dd StartPMP		; 32 bit offset
   549 0000049C 0800                    	dw KCODE		; kernel code segment descriptor
   550                                  
   551                                  
   552                                  StartPMP:
   553                                  	; 06/11//2014
   554                                  	; Clear video page 0
   555                                  	;
   556                                  	; Temporary Code
   557                                  	;
   558 0000049E B9E8030000              	mov	ecx, 80*25/2
   559 000004A3 BF00800B00              	mov	edi, 0B8000h
   560 000004A8 31C0                    	xor	eax, eax	; black background, black fore color
   561 000004AA F3AB                    	rep	stosd
   562                                  	
   563                                  	; 19/08/2014
   564                                  	; Kernel Base Address = 0
   565                                  	; It is mapped to (physically) 0 in the page table.
   566                                  	; So, here is exactly 'StartPMP' address.
   567                                  	;
   568                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   569                                  	;;mov	esi, msgPM
   570                                  	;; 14/08/2015 (kernel version message will appear
   571                                  	;;	       when protected mode and paging is enabled)
   572 000004AC B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   573 000004AE BE[A45D0000]            	mov	esi, msgKVER
   574 000004B3 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   575                                  	; 20/08/2014
   576 000004B8 E892010000              	call	printk
   577                                  
   578                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   579                                  	; // Set IRQ offsets
   580                                  	;
   581                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   582                                  	;
   583                                  					;; ICW1
   584 000004BD B011                    	mov	al, 11h			; Initialization sequence
   585 000004BF E620                    	out	20h, al			; 	8259A-1
   586                                  	; jmp 	$+2
   587 000004C1 E6A0                    	out	0A0h, al		; 	8259A-2
   588                                  					;; ICW2
   589 000004C3 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   590 000004C5 E621                    	out	21h, al			;	for 8259A-1
   591                                  	; jmp 	$+2
   592 000004C7 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   593 000004C9 E6A1                    	out	0A1h, al		; 	for 8259A-2
   594                                  					;
   595 000004CB B004                    	mov	al, 04h			;; ICW3
   596 000004CD E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   597                                  	; jmp 	$+2
   598 000004CF B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   599 000004D1 E6A1                    	out	0A1h, al		;
   600                                  					;; ICW4
   601 000004D3 B001                    	mov	al, 01h	 		;
   602 000004D5 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   603                                  	; jmp 	$+2
   604 000004D7 E6A1                    	out	0A1h, al		;	for both chips.
   605                                  
   606                                  	;mov	al, 0FFh	; mask off all interrupts for now
   607                                  	;out	21h, al
   608                                  	;; jmp 	$+2
   609                                  	;out	0A1h, al
   610                                  
   611                                  	; 02/04/2015
   612                                  	; 26/03/2015 System call (INT 30h) modification
   613                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   614                                  	;
   615                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   616                                  	;  setup_idt:
   617                                  	;
   618                                          ;; 16/02/2015
   619                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   620                                  	; 21/08/2014 (timer_int)
   621 000004D9 BE[9C5A0000]            	mov	esi, ilist
   622 000004DE 8D3D[E05F0000]          	lea	edi, [idt]
   623                                  	; 26/03/2015
   624 000004E4 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   625                                  	; 02/04/2015
   626 000004E9 BB00000800              	mov	ebx, 80000h
   627                                  rp_sidt1:
   628 000004EE AD                      	lodsd
   629 000004EF 89C2                    	mov	edx, eax
   630 000004F1 66BA008E                	mov	dx, 8E00h
   631 000004F5 6689C3                  	mov	bx, ax
   632 000004F8 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   633                                         			        ; /* interrupt gate - dpl=0, present */
   634 000004FA AB                      	stosd	; selector & offset bits 0-15 	
   635 000004FB 89D0                    	mov	eax, edx
   636 000004FD AB                      	stosd	; attributes & offset bits 16-23
   637 000004FE E2EE                    	loop	rp_sidt1
   638 00000500 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   639                                  rp_sidt2:
   640 00000502 AD                      	lodsd
   641 00000503 21C0                    	and	eax, eax
   642 00000505 7413                    	jz	short rp_sidt3
   643 00000507 89C2                    	mov	edx, eax
   644 00000509 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   645 0000050D 6689C3                  	mov	bx, ax
   646 00000510 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   647 00000512 AB                      	stosd
   648 00000513 89D0                    	mov	eax, edx
   649 00000515 AB                      	stosd
   650 00000516 E2EA                    	loop	rp_sidt2
   651 00000518 EB16                    	jmp	short sidt_OK
   652                                  rp_sidt3:
   653 0000051A B8[72090000]            	mov	eax, ignore_int
   654 0000051F 89C2                    	mov	edx, eax
   655 00000521 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   656 00000525 6689C3                  	mov	bx, ax
   657 00000528 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   658                                  rp_sidt4:
   659 0000052A AB                      	stosd
   660 0000052B 92                      	xchg	eax, edx
   661 0000052C AB                      	stosd
   662 0000052D 92                      	xchg	edx, eax
   663 0000052E E2FA                    	loop	rp_sidt4
   664                                  sidt_OK: 
   665 00000530 0F011D[965A0000]        	lidt 	[idtd]
   666                                  	;
   667                                  	; TSS descriptor setup ; 24/03/2015
   668 00000537 B8[E0610000]            	mov	eax, task_state_segment
   669 0000053C 66A3[8A5A0000]          	mov	[gdt_tss0], ax
   670 00000542 C1C010                  	rol	eax, 16
   671 00000545 A2[8C5A0000]            	mov	[gdt_tss1], al
   672 0000054A 8825[8F5A0000]          	mov	[gdt_tss2], ah
   673 00000550 66C705[46620000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   673 00000558 00                 
   674                                  		; 
   675                                  		; IO Map Base address (When this address points
   676                                  		; to end of the TSS, CPU does not use IO port 
   677                                  		; permission bit map for RING 3 IO permissions, 
   678                                  		; access to any IO ports in ring 3 will be forbidden.)
   679                                   		;
   680                                  	;mov	[tss.esp0], esp ; TSS offset 4
   681                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   682 00000559 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   683                                  			 ; occurs (or a system call -software INT- is requested)
   684                                  			 ; while cpu running in ring 3 (in user mode).				
   685                                  			 ; (Kernel stack pointer and segment will be loaded
   686                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   687 0000055D 0F00D8                  	ltr	ax  ; Load task register
   688                                  	;
   689                                  esp0_set0:
   690                                  	; 30/07/2015
   691 00000560 8B0D[4C620000]          	mov 	ecx, [memory_size] ; memory size in pages
   692 00000566 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   693 00000569 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   694                                  			  ; (kernel mode virtual address)
   695 0000056F 7605                    	jna	short esp0_set1
   696                                  	;
   697                                  	; If available memory > CORE (end of the 1st 4 MB)
   698                                  	; set stack pointer to CORE
   699                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   700                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   701 00000571 B900004000              	mov	ecx, CORE
   702                                  esp0_set1:
   703 00000576 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   704                                  esp0_set_ok:
   705                                  	; 30/07/2015 (**tss.esp0**) 
   706 00000578 8925[E4610000]          	mov	[tss.esp0], esp
   707 0000057E 66C705[E8610000]10-             mov     word [tss.ss0], KDATA
   707 00000586 00                 
   708                                  	; 14/08/2015
   709                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   710                                  	;
   711                                  	;cli	; Disable interrupts (for CPU)
   712                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   713                                  	;
   714 00000587 30C0                    	xor	al, al		; Enable all hardware interrupts!
   715 00000589 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   716 0000058B EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   717 0000058D E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   718                                  				; (Even if related hardware component
   719                                  				;  does not exist!)
   720                                  	; Enable NMI 
   721 0000058F B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   722 00000591 E670                    	out  	70h, al
   723                                  	; 23/02/2015
   724 00000593 90                      	nop
   725 00000594 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   726                                  				; for preventing unknown state (!?)
   727                                  	;
   728                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   729                                  	;
   730                                  	; 02/09/2014
   731                                  	;xor	bx, bx
   732                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   733                                  	; 27/02/2022	
   734 00000596 31DB                    	xor	ebx, ebx
   735 00000598 31D2                    	xor	edx, edx
   736 0000059A B602                    	mov	dh, 2
   737 0000059C E8250F0000              	call	set_cpos
   738                                  	;
   739                                  	; 06/11/2014
   740                                  	; Temporary Code
   741                                  	;
   742 000005A1 E89A100000              	call	memory_info
   743                                  	; 14/08/2015
   744                                  	;call getch ; 28/02/2015
   745                                  drv_init:
   746 000005A6 FB                      	sti	; Enable Interrupts 
   747                                  	; 06/02/2015
   748 000005A7 8B15[6E5D0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   749 000005AD 668B1D[6C5D0000]        	mov	bx, [fd0_type] ; fd0, fd1
   750                                  	; 22/02/2015
   751 000005B4 6621DB                  	and	bx, bx
   752 000005B7 751B                    	jnz	short di1
   753                                  	;
   754 000005B9 09D2                    	or 	edx, edx
   755 000005BB 7529                    	jnz	short di2
   756                                  	;
   757                                  setup_error:
   758 000005BD BE[8B5E0000]            	mov 	esi, setup_error_msg
   759                                  psem:	
   760 000005C2 AC                      	lodsb
   761 000005C3 08C0                    	or	al, al
   762                                  	;jz	short haltx ; 22/02/2015
   763 000005C5 7426                    	jz	short di3
   764 000005C7 56                      	push	esi
   765 000005C8 31DB                    	xor	ebx, ebx ; 0
   766                                  			; Video page 0 (bl=0)
   767 000005CA B407                    	mov	ah, 07h ; Black background, 
   768                                  			; light gray forecolor
   769 000005CC E8EB0D0000              	call	write_tty
   770 000005D1 5E                      	pop	esi
   771 000005D2 EBEE                    	jmp	short psem
   772                                  
   773                                  di1:
   774                                  	; supress 'jmp short T6'
   775                                  	;  (activate fdc motor control code)
   776 000005D4 66C705[D0060000]90-     	mov	word [T5], 9090h ; nop
   776 000005DC 90                 
   777                                  	;
   778                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   779                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   780                                  	;stosw
   781                                  	;mov 	ax, cs
   782                                  	;stosw
   783                                  	;; 16/02/2015
   784                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   785                                  	;
   786 000005DD E8221A0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   787                                  	;
   788 000005E2 09D2                    	or	edx, edx
   789 000005E4 7407                            jz      short di3
   790                                  di2:
   791 000005E6 E84B1A0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   792 000005EB 72D0                            jc      short setup_error
   793                                  di3:
   794 000005ED E822100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   795                                  	;
   796 000005F2 E8C6530000              	call	display_disks ; 07/03/2015  (Temporary)
   797                                  ;haltx:
   798                                  	; 14/08/2015
   799                                  	;call	getch ; 22/02/2015
   800 000005F7 FB                      	sti	; Enable interrupts (for CPU)
   801                                  	; 14/08/2015
   802                                  	;mov 	ecx, 0FFFFFFFh
   803                                  	; 16/02/2022
   804 000005F8 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   805                                  md_info_msg_wait:
   806 000005FD 51                      	push 	ecx
   807 000005FE B001                    	mov	al, 1
   808 00000600 8A25[76620000]          	mov 	ah, [ptty] ; active (current) video page
   809 00000606 E89D500000              	call	getc_n
   810 0000060B 59                      	pop	ecx
   811 0000060C 7502                    	jnz	short md_info_msg_ok
   812 0000060E E2ED                    	loop	md_info_msg_wait
   813                                  md_info_msg_ok:
   814                                  	; 30/06/2015
   815 00000610 E8E4230000              	call	sys_init
   816                                  	;
   817                                  	;jmp 	cpu_reset ; 22/02/2015
   818                                  hang:
   819                                  	; 27/02/2022
   820 00000615 29C0                    	sub	eax, eax
   821                                  _hang: 
   822                                  	; 23/02/2015
   823                                  	;sti			; Enable interrupts
   824 00000617 F4                      	hlt
   825                                  	;
   826                                  	;nop
   827                                  	;; 03/12/2014
   828                                  	;; 28/08/2014
   829                                  	;mov	ah, 11h
   830                                  	;call	getc
   831                                  	;jz      _c8
   832                                  	;
   833                                  	; 23/02/2015
   834                                  	; 06/02/2015
   835                                  	; 07/09/2014
   836 00000618 31DB                    	xor	ebx, ebx
   837 0000061A 8A1D[76620000]          	mov	bl, [ptty]	; active_page
   838 00000620 89DE                    	mov	esi, ebx
   839 00000622 66D1E6                  	shl 	si, 1
   840 00000625 81C6[78620000]          	add	esi, ttychr
   841 0000062B 668B06                  	mov	ax, [esi]
   842                                  	;and	ax, ax
   843                                  	;;jz	short _c8
   844                                  	;jz	short hang
   845                                  	; 27/02/2022
   846 0000062E 21C0                    	and	eax, eax
   847 00000630 74E5                    	jz	short _hang
   848 00000632 66C7060000              	mov	word [esi], 0
   849 00000637 80FB03                  	cmp	bl, 3		; Video page 3
   850                                  	;jb	short _c8
   851 0000063A 72D9                    	jb	short hang
   852                                  	;	
   853                                  	; 02/09/2014
   854 0000063C B40E                    	mov	ah, 0Eh		; Yellow character 
   855                                  				; on black background
   856                                  	; 27/02/2022 (32 bit reg push-pop)
   857                                  	; 07/09/2014
   858                                  nxtl:
   859                                  	;push	bx
   860 0000063E 53                      	push	ebx
   861                                  	;
   862                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   863                                  				; bh = 0 (video mode)
   864                                  				; Retro UNIX 386 v1 - Video Mode 0
   865                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   866 0000063F 50                      	push	eax
   867 00000640 E8770D0000              	call 	write_tty
   868 00000645 58                      	pop	eax
   869                                  	;pop	bx
   870 00000646 5B                      	pop	ebx
   871 00000647 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   872                                  	;jne	short _c8
   873 00000649 75CA                    	jne	short hang
   874 0000064B B00A                    	mov	al, 0Ah		; next line
   875 0000064D EBEF                    	jmp	short nxtl
   876                                  	
   877                                  ;_c8:
   878                                  ;	; 25/08/2014
   879                                  ;	cli				; Disable interrupts
   880                                  ;	mov	al, [scounter + 1]
   881                                  ;	and	al, al
   882                                  ;	jnz	hang
   883                                  ;	call	rtc_p
   884                                  ;	jmp     hang
   885                                  
   886                                  
   887                                  	; 27/08/2014
   888                                  	; 20/08/2014
   889                                  printk:
   890                                          ;mov    edi, [scr_row]
   891                                  pkl:
   892 0000064F AC                      	lodsb
   893 00000650 08C0                    	or 	al, al
   894 00000652 7404                    	jz	short pkr
   895 00000654 66AB                    	stosw
   896 00000656 EBF7                    	jmp	short pkl
   897                                  pkr:
   898 00000658 C3                      	retn
   899                                  
   900                                  ; 25/07/2015
   901                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   902                                  ; 17/02/2015
   903                                  ; 06/02/2015 (unix386.s)
   904                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   905                                  ;
   906                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   907                                  ;
   908                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   909                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   910                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   911                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   912                                  ;									       :
   913                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   914                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   915                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   916                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   917                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   918                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   919                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   920                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   921                                  ;-------------------------------------------------------------------------------
   922                                  ;
   923                                  
   924                                  timer_int:	; IRQ 0
   925                                  ;int_08h:	; Timer
   926                                  	; 14/10/2015
   927                                  	; Here, we are simulating system call entry (for task switch)
   928                                  	; (If multitasking is enabled, 
   929                                  	; 'clock' procedure may jump to 'sysrelease')
   930 00000659 1E                      	push	ds
   931 0000065A 06                      	push	es
   932 0000065B 0FA0                    	push	fs
   933 0000065D 0FA8                    	push	gs
   934 0000065F 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   935 00000660 66B91000                	mov     cx, KDATA
   936 00000664 8ED9                            mov     ds, cx
   937 00000666 8EC1                            mov     es, cx
   938 00000668 8EE1                            mov     fs, cx
   939 0000066A 8EE9                            mov     gs, cx
   940                                  	;
   941 0000066C 0F20D9                  	mov	ecx, cr3
   942 0000066F 890D[12070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   943                                  	;
   944 00000675 3B0D[48620000]          	cmp 	ecx, [k_page_dir]
   945 0000067B 741F                    	je	short T3
   946                                  	;
   947                                  	; timer interrupt has been occurred while OS is in user mode
   948 0000067D A3[10660000]            	mov 	[u.r0], eax
   949 00000682 89E1                    	mov	ecx, esp
   950 00000684 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   951 00000687 890D[08660000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   952 0000068D 8925[0C660000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   953                                  	;
   954 00000693 8B0D[48620000]          	mov	ecx, [k_page_dir]
   955 00000699 0F22D9                  	mov	cr3, ecx
   956                                  T3:
   957 0000069C FB                      	sti				; INTERRUPTS BACK ON
   958 0000069D 66FF05[C4620000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   959 000006A4 7507                    	JNZ	short T4		; GO TO TEST_DAY
   960 000006A6 66FF05[C6620000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   961                                  T4:					; TEST_DAY
   962 000006AD 66833D[C6620000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   963 000006B5 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   964 000006B7 66813D[C4620000]B0-     	CMP	word [TIMER_LOW],0B0H
   964 000006BF 00                 
   965 000006C0 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   966                                  
   967                                  ;-----	TIMER HAS GONE 24 HOURS
   968                                  	;;SUB	AX,AX
   969                                  	;MOV	[TIMER_HIGH],AX
   970                                  	;MOV	[TIMER_LOW],AX
   971 000006C2 29C0                    	sub	eax, eax
   972 000006C4 A3[C4620000]            	mov	[TIMER_LH], eax
   973                                  	;	
   974 000006C9 C605[C8620000]01        	MOV	byte [TIMER_OFL],1
   975                                  
   976                                  ;-----	TEST FOR DISKETTE TIME OUT
   977                                  
   978                                  T5:
   979                                  	; 23/12/2014
   980 000006D0 EB1D                    	jmp	short T6		; will be replaced with nop, nop
   981                                  					; (9090h) if a floppy disk
   982                                  					; is detected.
   983                                  	;mov	al,[CS:MOTOR_COUNT]
   984 000006D2 A0[CB620000]            	mov	al, [MOTOR_COUNT]
   985 000006D7 FEC8                    	dec	al
   986                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   987 000006D9 A2[CB620000]            	mov	[MOTOR_COUNT], al
   988                                  	;mov	[ORG_MOTOR_COUNT], al
   989 000006DE 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   990 000006E0 B0F0                    	mov 	al,0F0h
   991                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   992 000006E2 2005[CA620000]          	and	[MOTOR_STATUS], al
   993                                  	;and	[ORG_MOTOR_STATUS], al
   994 000006E8 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   995                                  					; bit 2 = enable controller
   996                                  					;	1 = normal operation
   997                                  					;	0 = reset	
   998                                  					; bit 0, 1 = drive select
   999                                  					; bit 4-7 = motor running bits 
  1000 000006EA 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1001 000006EE EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1002                                  T6:	
  1003                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1004                                  					; TIMER TICK INTERRUPT
  1005                                  	;;inc	word [wait_count] ;;27/02/2015
  1006                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1007                                  	;;;;cli
  1008                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1009 000006EF FF15[0A070000]          	call	[x_timer] ; 14/05/2015
  1010                                  T7:
  1011                                  	; 14/10/2015
  1012 000006F5 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1013 000006F7 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1014 000006F8 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1015                                  	;
  1016 000006FA A1[12070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1017 000006FF 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1018                                  	;
  1019 00000702 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1020                                  	;
  1021 00000703 0FA9                    	pop	gs
  1022 00000705 0FA1                    	pop	fs
  1023 00000707 07                      	pop	es
  1024 00000708 1F                      	pop	ds
  1025 00000709 CF                      	iretd	; return from interrupt
  1026                                  
  1027                                  
  1028                                  ; ////////////////
  1029                                  
  1030                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1031                                  x_timer:
  1032 0000070A [16070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1033                                  	;dd	clock
  1034                                  
  1035                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1036                                  x_rtci:
  1037 0000070E [4B0A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1038                                  
  1039                                  ; 14/10/2015
  1040 00000712 00000000                cr3reg: dd 0
  1041                                  
  1042                                  	; 06/02/2015
  1043                                  	; 07/09/2014
  1044                                  	; 21/08/2014
  1045                                  u_timer:
  1046                                  	; 27/02/2022
  1047                                  	; 12/02/2022
  1048                                  ;timer_int:	; IRQ 0
  1049                                  	; 06/02/2015
  1050                                  	;push	eax
  1051                                  	;push	edx
  1052                                  	;push	ecx
  1053                                  	;push	ebx
  1054                                  	;push	ds
  1055                                  	;push	es
  1056                                  	;mov	eax, KDATA
  1057                                  	;mov	ds, ax
  1058                                  	;mov	es, ax
  1059 00000716 FF05[8C620000]          	inc	dword [tcount]
  1060 0000071C BB[145E0000]            	mov	ebx, tcountstr + 4
  1061                                  	;mov	ax, [tcount]
  1062                                  	; 27/02/2022
  1063 00000721 A1[8C620000]            	mov	eax, [tcount]
  1064                                  	;mov	ecx, 10
  1065 00000726 31C9                    	xor	ecx, ecx
  1066 00000728 B10A                    	mov	cl, 10
  1067                                  rp_divtcnt:
  1068 0000072A 31D2                    	xor	edx, edx
  1069 0000072C F7F1                    	div	ecx
  1070 0000072E 80C230                  	add	dl, 30h
  1071 00000731 8813                    	mov	[ebx], dl
  1072                                  	;or	ax, ax
  1073                                  	; 27/02/2022
  1074 00000733 09C0                    	or	eax, eax
  1075 00000735 7403                    	jz	short print_lzero
  1076 00000737 4B                      	dec	ebx
  1077 00000738 EBF0                    	jmp	short rp_divtcnt
  1078                                  print_lzero:
  1079 0000073A 81FB[105E0000]          	cmp	ebx, tcountstr
  1080 00000740 7606                    	jna	short print_tcount
  1081 00000742 4B                      	dec	ebx
  1082 00000743 C60330                   	mov	byte [ebx], 30h
  1083 00000746 EBF2                    	jmp	short print_lzero
  1084                                  print_tcount:
  1085 00000748 56                      	push	esi
  1086 00000749 57                      	push	edi
  1087 0000074A BE[EC5D0000]            	mov	esi, timer_msg ; Timer interrupt message
  1088                                  	;; 07/09/2014
  1089                                  	;mov	bx, 1		; Video page 1
  1090                                  	; 12/02/2022
  1091                                  	;mov	bx, 6		; Video page 6
  1092                                  	; 27/02/2022
  1093 0000074F 29DB                    	sub	ebx, ebx
  1094 00000751 B306                    	mov	bl, 6	; Video page 6
  1095                                  ptmsg:
  1096 00000753 AC                      	lodsb
  1097 00000754 08C0                    	or	al, al
  1098 00000756 740D                    	jz	short ptmsg_ok
  1099 00000758 56                      	push	esi
  1100                                  	;push	bx
  1101                                  	; 27/02/2022
  1102 00000759 53                              push	ebx
  1103 0000075A B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1104 0000075C E85B0C0000              	call 	write_tty
  1105                                  	;pop	bx
  1106                                  	; 27/02/2022
  1107 00000761 5B                      	pop	ebx
  1108 00000762 5E                      	pop	esi
  1109 00000763 EBEE                    	jmp	short ptmsg
  1110                                  	;; 27/08/2014
  1111                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1112                                  	;call	printk
  1113                                  	;
  1114                                  ptmsg_ok:
  1115                                  	; 07/09/2014
  1116                                  	;xor	dx, dx		; column 0, row 0
  1117                                  	; 27/02/2022
  1118 00000765 31D2                    	xor	edx, edx
  1119 00000767 E85A0D0000              	call	set_cpos	; set cursor position to 0,0 
  1120                                  	; 23/02/2015
  1121                                  	; 25/08/2014
  1122                                  	;mov	ebx, scounter		; (seconds counter)
  1123                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1124                                  ;	dec	byte [scounter+1]
  1125                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1126                                  ;	jns	short u_timer_retn
  1127                                  	; 26/02/2015
  1128                                  ;	call	rtc_p
  1129                                  ;	mov	ebx, scounter		; (seconds counter)
  1130                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1131                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1132                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1133                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1134                                  ;	mov	byte [ebx], 5
  1135                                  ;	inc	byte [ebx+1] ; 19
  1136                                  ;;timer_eoi:
  1137                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1138                                  ;;	out	20h, al	; 8259 PORT
  1139                                  	;
  1140                                  ;u_timer_retn:  ; 06/02/2015
  1141 0000076C 5F                      	pop	edi
  1142 0000076D 5E                      	pop	esi
  1143                                  	;pop	es
  1144                                  	;pop	ds
  1145                                  	;pop	ebx
  1146                                  	;pop	ecx
  1147                                  	;pop	edx
  1148                                  	;pop	eax
  1149                                  	;iret
  1150 0000076E C3                      	retn	; 06/02/2015
  1151                                  
  1152                                  	; 28/08/2014
  1153                                  irq0:
  1154 0000076F 6A00                            push 	dword 0
  1155 00000771 EB48                    	jmp	short which_irq
  1156                                  irq1:
  1157 00000773 6A01                            push 	dword 1
  1158 00000775 EB44                    	jmp	short which_irq
  1159                                  irq2:
  1160 00000777 6A02                            push 	dword 2
  1161 00000779 EB40                    	jmp	short which_irq
  1162                                  irq3:
  1163                                  	; 20/11/2015
  1164                                  	; 24/10/2015
  1165 0000077B 2EFF15[0A310000]        	call	dword [cs:com2_irq3]
  1166 00000782 6A03                    	push 	dword 3
  1167 00000784 EB35                    	jmp	short which_irq
  1168                                  irq4:
  1169                                  	; 20/11/2015
  1170                                  	; 24/10/2015
  1171 00000786 2EFF15[06310000]        	call	dword [cs:com1_irq4]
  1172 0000078D 6A04                            push 	dword 4
  1173 0000078F EB2A                    	jmp	short which_irq
  1174                                  irq5:
  1175 00000791 6A05                            push 	dword 5
  1176 00000793 EB26                    	jmp	short which_irq
  1177                                  irq6:
  1178 00000795 6A06                            push 	dword 6
  1179 00000797 EB22                    	jmp	short which_irq
  1180                                  irq7:
  1181 00000799 6A07                            push 	dword 7
  1182 0000079B EB1E                    	jmp	short which_irq
  1183                                  irq8:
  1184 0000079D 6A08                            push 	dword 8
  1185 0000079F EB1A                    	jmp	short which_irq
  1186                                  irq9:
  1187 000007A1 6A09                            push 	dword 9
  1188 000007A3 EB16                    	jmp	short which_irq
  1189                                  irq10:
  1190 000007A5 6A0A                            push 	dword 10
  1191 000007A7 EB12                    	jmp	short which_irq
  1192                                  irq11:
  1193 000007A9 6A0B                            push 	dword 11
  1194 000007AB EB0E                    	jmp	short which_irq
  1195                                  irq12:
  1196 000007AD 6A0C                            push 	dword 12
  1197 000007AF EB0A                    	jmp	short which_irq
  1198                                  irq13:
  1199 000007B1 6A0D                            push 	dword 13
  1200 000007B3 EB06                    	jmp	short which_irq
  1201                                  irq14:
  1202 000007B5 6A0E                            push 	dword 14
  1203 000007B7 EB02                    	jmp	short which_irq
  1204                                  irq15:
  1205 000007B9 6A0F                            push 	dword 15
  1206                                  	;jmp	short which_irq
  1207                                  
  1208                                  	; 27/02/2022
  1209                                  	; 19/10/2015
  1210                                  	; 29/08/2014
  1211                                  	; 21/08/2014
  1212                                  which_irq:
  1213 000007BB 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1214 000007BE 53                      	push	ebx
  1215 000007BF 56                      	push	esi
  1216 000007C0 57                      	push	edi
  1217 000007C1 1E                      	push 	ds
  1218 000007C2 06                      	push 	es
  1219                                  	;
  1220 000007C3 88C3                    	mov	bl, al
  1221                                  	;
  1222 000007C5 B810000000              	mov	eax, KDATA
  1223 000007CA 8ED8                    	mov	ds, ax
  1224 000007CC 8EC0                    	mov	es, ax
  1225                                  	; 19/10/2015
  1226 000007CE FC                      	cld
  1227                                          ; 27/08/2014
  1228 000007CF 8105[9C5D0000]A000-             add     dword [scr_row], 0A0h
  1228 000007D7 0000               
  1229                                  	;
  1230 000007D9 B417                    	mov	ah, 17h	; blue (1) background, 
  1231                                  			; light gray (7) forecolor
  1232 000007DB 8B3D[9C5D0000]                  mov     edi, [scr_row]
  1233 000007E1 B049                    	mov	al, 'I'
  1234 000007E3 66AB                    	stosw
  1235 000007E5 B052                    	mov	al, 'R'
  1236 000007E7 66AB                    	stosw
  1237 000007E9 B051                    	mov	al, 'Q'
  1238 000007EB 66AB                    	stosw
  1239 000007ED B020                    	mov	al, ' '
  1240 000007EF 66AB                    	stosw
  1241 000007F1 88D8                    	mov	al, bl
  1242 000007F3 3C0A                    	cmp	al, 10
  1243 000007F5 7208                    	jb	short iix
  1244 000007F7 B031                    	mov	al, '1'
  1245 000007F9 66AB                    	stosw
  1246 000007FB 88D8                    	mov	al, bl
  1247 000007FD 2C0A                    	sub	al, 10
  1248                                  iix:
  1249 000007FF 0430                    	add	al, '0'
  1250 00000801 66AB                    	stosw
  1251 00000803 B020                    	mov	al, ' '
  1252 00000805 66AB                    	stosw
  1253 00000807 B021                    	mov	al, '!'
  1254 00000809 66AB                    	stosw
  1255 0000080B B020                    	mov	al, ' '
  1256 0000080D 66AB                    	stosw
  1257                                  	; 23/02/2015
  1258 0000080F 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1259                                  	;jna	iiret
  1260                                  	; 27/02/2022
  1261 00000812 7604                    	jna	short iiz
  1262                                  iiy:
  1263 00000814 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1264 00000816 E6A0                    	out	0A0h, al ; the 2nd 8259
  1265                                  iiz:
  1266 00000818 E983010000              	jmp     iiret
  1267                                  	;
  1268                                  	; 22/08/2014
  1269                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1270                                  	;out	20h, al	; 8259 PORT
  1271                                  	;
  1272                                  	;pop	es
  1273                                  	;pop	ds
  1274                                  	;pop	edi
  1275                                  	;pop	esi
  1276                                  	;pop	ebx
  1277                                  	;pop 	eax
  1278                                  	;iret
  1279                                  
  1280                                  	; 02/04/2015
  1281                                  	; 25/08/2014
  1282                                  exc0:
  1283 0000081D 6A00                            push 	dword 0
  1284 0000081F E990000000                      jmp     cpu_except
  1285                                  exc1:
  1286 00000824 6A01                            push 	dword 1
  1287 00000826 E989000000                      jmp     cpu_except
  1288                                  exc2:
  1289 0000082B 6A02                            push 	dword 2
  1290 0000082D E982000000                      jmp     cpu_except
  1291                                  exc3:
  1292 00000832 6A03                            push 	dword 3
  1293 00000834 EB7E                            jmp     cpu_except
  1294                                  exc4:
  1295 00000836 6A04                            push 	dword 4
  1296 00000838 EB7A                            jmp     cpu_except
  1297                                  exc5:
  1298 0000083A 6A05                            push 	dword 5
  1299 0000083C EB76                            jmp     cpu_except
  1300                                  exc6:
  1301 0000083E 6A06                            push 	dword 6
  1302 00000840 EB72                            jmp     cpu_except
  1303                                  exc7:
  1304 00000842 6A07                            push 	dword 7
  1305 00000844 EB6E                            jmp     cpu_except
  1306                                  exc8:
  1307                                  	; [esp] = Error code
  1308 00000846 6A08                            push 	dword 8
  1309 00000848 EB5C                            jmp     cpu_except_en
  1310                                  exc9:
  1311 0000084A 6A09                            push 	dword 9
  1312 0000084C EB66                            jmp     cpu_except
  1313                                  exc10:
  1314                                  	; [esp] = Error code
  1315 0000084E 6A0A                            push 	dword 10
  1316 00000850 EB54                            jmp     cpu_except_en
  1317                                  exc11:
  1318                                  	; [esp] = Error code
  1319 00000852 6A0B                            push 	dword 11
  1320 00000854 EB50                            jmp     cpu_except_en
  1321                                  exc12:
  1322                                  	; [esp] = Error code
  1323 00000856 6A0C                            push 	dword 12
  1324 00000858 EB4C                            jmp     cpu_except_en
  1325                                  exc13:
  1326                                  	; [esp] = Error code
  1327 0000085A 6A0D                            push 	dword 13
  1328 0000085C EB48                            jmp     cpu_except_en
  1329                                  exc14:
  1330                                  	; [esp] = Error code
  1331 0000085E 6A0E                            push 	dword 14
  1332 00000860 EB44                    	jmp	short cpu_except_en
  1333                                  exc15:
  1334 00000862 6A0F                            push 	dword 15
  1335 00000864 EB4E                            jmp     cpu_except
  1336                                  exc16:
  1337 00000866 6A10                            push 	dword 16
  1338 00000868 EB4A                            jmp     cpu_except
  1339                                  exc17:
  1340                                  	; [esp] = Error code
  1341 0000086A 6A11                            push 	dword 17
  1342 0000086C EB38                    	jmp	short cpu_except_en
  1343                                  exc18:
  1344 0000086E 6A12                            push 	dword 18
  1345 00000870 EB42                    	jmp	short cpu_except
  1346                                  exc19:
  1347 00000872 6A13                            push 	dword 19
  1348 00000874 EB3E                    	jmp	short cpu_except
  1349                                  exc20:
  1350 00000876 6A14                            push 	dword 20
  1351 00000878 EB3A                    	jmp	short cpu_except
  1352                                  exc21:
  1353 0000087A 6A15                            push 	dword 21
  1354 0000087C EB36                    	jmp	short cpu_except
  1355                                  exc22:
  1356 0000087E 6A16                            push 	dword 22
  1357 00000880 EB32                    	jmp	short cpu_except
  1358                                  exc23:
  1359 00000882 6A17                            push 	dword 23
  1360 00000884 EB2E                    	jmp	short cpu_except
  1361                                  exc24:
  1362 00000886 6A18                            push 	dword 24
  1363 00000888 EB2A                    	jmp	short cpu_except
  1364                                  exc25:
  1365 0000088A 6A19                            push 	dword 25
  1366 0000088C EB26                    	jmp	short cpu_except
  1367                                  exc26:
  1368 0000088E 6A1A                            push 	dword 26
  1369 00000890 EB22                    	jmp	short cpu_except
  1370                                  exc27:
  1371 00000892 6A1B                            push 	dword 27
  1372 00000894 EB1E                    	jmp	short cpu_except
  1373                                  exc28:
  1374 00000896 6A1C                            push 	dword 28
  1375 00000898 EB1A                    	jmp	short cpu_except
  1376                                  exc29:
  1377 0000089A 6A1D                            push 	dword 29
  1378 0000089C EB16                    	jmp	short cpu_except
  1379                                  exc30:
  1380 0000089E 6A1E                            push 	dword 30
  1381 000008A0 EB04                    	jmp	short cpu_except_en
  1382                                  exc31:
  1383 000008A2 6A1F                            push 	dword 31
  1384 000008A4 EB0E                            jmp     short cpu_except
  1385                                  
  1386                                  	; 27/02/2022
  1387                                  	; 19/10/2015
  1388                                  	; 19/09/2015
  1389                                  	; 01/09/2015
  1390                                  	; 28/08/2015
  1391                                  	; 28/08/2014
  1392                                  cpu_except_en:
  1393 000008A6 87442404                	xchg	eax, [esp+4] ; Error code
  1394 000008AA 36A3[F4620000]          	mov	[ss:error_code], eax
  1395 000008B0 58                      	pop	eax  ; Exception number
  1396 000008B1 870424                  	xchg	eax, [esp]
  1397                                  		; eax = eax before exception
  1398                                  		; [esp] -> exception number
  1399                                  		; [esp+4] -> EIP to return
  1400                                  	; 19/10/2015
  1401                                  	; 19/09/2015
  1402                                  	; 01/09/2015
  1403                                  	; 28/08/2015
  1404                                  	; 29/08/2014
  1405                                  	; 28/08/2014
  1406                                  	; 25/08/2014
  1407                                  	; 21/08/2014
  1408                                  cpu_except:	; CPU Exceptions
  1409 000008B4 FC                      	cld
  1410 000008B5 870424                  	xchg	eax, [esp] 
  1411                                  		; eax = Exception number
  1412                                  		; [esp] = eax (before exception)	
  1413 000008B8 53                      	push	ebx
  1414 000008B9 56                      	push	esi
  1415 000008BA 57                      	push	edi
  1416 000008BB 1E                      	push 	ds
  1417 000008BC 06                      	push 	es
  1418                                  	; 28/08/2015
  1419 000008BD 66BB1000                	mov	bx, KDATA
  1420 000008C1 8EDB                    	mov	ds, bx
  1421 000008C3 8EC3                    	mov	es, bx
  1422 000008C5 0F20DB                  	mov	ebx, cr3
  1423 000008C8 53                      	push	ebx ; (*) page directory
  1424                                  	; 19/10/2015
  1425 000008C9 FC                      	cld
  1426                                  	; 25/03/2015
  1427 000008CA 8B1D[48620000]          	mov	ebx, [k_page_dir]
  1428 000008D0 0F22DB                  	mov	cr3, ebx
  1429                                  	; 28/08/2015
  1430 000008D3 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1431 000008D6 7513                    	jne	short cpu_except_nfp
  1432 000008D8 E8D61E0000              	call	page_fault_handler
  1433 000008DD 21C0                    	and 	eax, eax
  1434                                          ;jz	iiretp ; 01/09/2015
  1435                                  	; 27/02/2022
  1436 000008DF 7505                    	jnz	short cpu_except_pf
  1437 000008E1 E9B6000000              	jmp	iiretp
  1438                                  cpu_except_pf:
  1439 000008E6 B80E000000              	mov	eax, 0Eh ; 14
  1440                                  cpu_except_nfp:
  1441                                  	; 02/04/2015
  1442 000008EB BB[15060000]            	mov	ebx, hang
  1443 000008F0 875C241C                	xchg	ebx, [esp+28]
  1444                                  		; EIP (points to instruction which faults)
  1445                                  	  	; New EIP (hang)
  1446 000008F4 891D[F8620000]          	mov	[FaultOffset], ebx
  1447 000008FA C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1448 00000902 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1449                                  	;
  1450 0000090A 88C4                    	mov	ah, al
  1451 0000090C 240F                    	and	al, 0Fh
  1452 0000090E 3C09                    	cmp	al, 9
  1453 00000910 7602                    	jna	short h1ok
  1454 00000912 0407                    	add	al, 'A'-':'
  1455                                  h1ok:
  1456 00000914 D0EC                    	shr	ah, 1
  1457 00000916 D0EC                    	shr	ah, 1
  1458 00000918 D0EC                    	shr	ah, 1
  1459 0000091A D0EC                    	shr	ah, 1
  1460 0000091C 80FC09                  	cmp	ah, 9
  1461 0000091F 7603                    	jna	short h2ok
  1462 00000921 80C407                  	add	ah, 'A'-':'
  1463                                  h2ok:	
  1464 00000924 86E0                    	xchg 	ah, al	
  1465 00000926 66053030                	add	ax, '00'
  1466 0000092A 66A3[285E0000]          	mov	[excnstr], ax
  1467                                  	;
  1468                                  	; 29/08/2014
  1469 00000930 A1[F8620000]            	mov	eax, [FaultOffset]
  1470 00000935 51                      	push	ecx
  1471 00000936 52                      	push	edx
  1472 00000937 89E3                    	mov	ebx, esp
  1473                                  	; 28/08/2015
  1474 00000939 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1475                                  			  ; to hexadecimal string
  1476                                  	;mov	ecx, 10	    ; divisor to convert	
  1477                                  			    ; binary number to decimal string
  1478                                  b2d1:
  1479 0000093E 31D2                    	xor	edx, edx
  1480 00000940 F7F1                    	div	ecx
  1481                                  	;push	dx
  1482                                  	; 27/02/2022
  1483 00000942 52                      	push	edx
  1484 00000943 39C8                    	cmp	eax, ecx
  1485 00000945 73F7                    	jnb	short b2d1
  1486 00000947 BF[335E0000]            	mov	edi, EIPstr ; EIP value
  1487                                  			    ; points to instruction which faults	
  1488                                  	; 28/08/2015
  1489 0000094C 89C2                    	mov	edx, eax
  1490                                  b2d2:
  1491                                  	;add	al, '0'
  1492 0000094E 8A82[FC160000]          	mov	al, [edx+hexchrs]
  1493 00000954 AA                      	stosb		    ; write hexadecimal digit to its place	
  1494 00000955 39E3                    	cmp	ebx, esp
  1495 00000957 7605                    	jna	short b2d3
  1496                                  	; 27/02/2022
  1497 00000959 58                      	pop	eax
  1498                                  	;pop	ax
  1499 0000095A 88C2                    	mov	dl, al
  1500 0000095C EBF0                    	jmp	short b2d2
  1501                                  b2d3:
  1502 0000095E B068                    	mov 	al, 'h' ; 28/08/2015
  1503 00000960 AA                      	stosb
  1504 00000961 B020                    	mov	al, 20h	    ; space
  1505 00000963 AA                      	stosb
  1506 00000964 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1507 00000966 AA                      	stosb
  1508                                  	;
  1509 00000967 5A                      	pop	edx
  1510 00000968 59                      	pop	ecx
  1511                                  	;
  1512 00000969 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1513                                  			; white (F) forecolor
  1514 0000096B BE[185E0000]            	mov	esi, exc_msg ; message offset
  1515                                  	;
  1516 00000970 EB11                    	jmp	short piemsg
  1517                                  	;
  1518                                          ;add    dword [scr_row], 0A0h
  1519                                          ;mov    edi, [scr_row]
  1520                                          ;
  1521                                  	;call 	printk
  1522                                  	;
  1523                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1524                                  	;out	20h, al	; 8259 PORT
  1525                                  	;
  1526                                  	;pop	es
  1527                                  	;pop	ds
  1528                                  	;pop	edi
  1529                                  	;pop	esi
  1530                                  	;pop 	eax
  1531                                  	;iret
  1532                                  	
  1533                                  	; 28/08/2015
  1534                                  	; 23/02/2015
  1535                                  	; 20/08/2014
  1536                                  ignore_int:
  1537 00000972 50                      	push	eax
  1538 00000973 53                      	push	ebx ; 23/02/2015
  1539 00000974 56                      	push	esi
  1540 00000975 57                      	push	edi
  1541 00000976 1E                      	push 	ds
  1542 00000977 06                      	push 	es
  1543                                  	; 28/08/2015
  1544 00000978 0F20D8                  	mov	eax, cr3
  1545 0000097B 50                      	push	eax ; (*) page directory
  1546                                  	;
  1547 0000097C B467                    	mov	ah, 67h	; brown (6) background, 
  1548                                  			; light gray (7) forecolor
  1549 0000097E BE[D65D0000]            	mov	esi, int_msg ; message offset
  1550                                  piemsg:
  1551                                          ; 27/08/2014
  1552 00000983 8105[9C5D0000]A000-             add     dword [scr_row], 0A0h
  1552 0000098B 0000               
  1553 0000098D 8B3D[9C5D0000]                  mov     edi, [scr_row]
  1554                                          ;
  1555 00000993 E8B7FCFFFF              	call 	printk
  1556                                  	;
  1557                                  	; 23/02/2015
  1558 00000998 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1559 0000099A E6A0                    	out	0A0h, al ; the 2nd 8259
  1560                                  iiretp: ; 01/09/2015
  1561                                  	; 28/08/2015
  1562 0000099C 58                      	pop	eax ; (*) page directory
  1563 0000099D 0F22D8                  	mov	cr3, eax
  1564                                  	;
  1565                                  iiret:
  1566                                  	; 22/08/2014
  1567 000009A0 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1568 000009A2 E620                    	out	20h, al	; 8259 PORT
  1569                                  	;
  1570 000009A4 07                      	pop	es
  1571 000009A5 1F                      	pop	ds
  1572 000009A6 5F                      	pop	edi
  1573 000009A7 5E                      	pop	esi
  1574 000009A8 5B                      	pop	ebx ; 29/08/2014
  1575 000009A9 58                      	pop 	eax
  1576 000009AA CF                      	iretd
  1577                                  
  1578                                  	; 23/02/2022
  1579                                  	; 26/02/2015
  1580                                  	; 07/09/2014
  1581                                  	; 25/08/2014
  1582                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1583                                  	; 22/08/2014
  1584 000009AB 50                      	push	eax
  1585 000009AC 53                      	push	ebx ; 29/08/2014
  1586 000009AD 56                      	push	esi
  1587 000009AE 57                      	push	edi
  1588 000009AF 1E                      	push 	ds
  1589 000009B0 06                      	push 	es
  1590                                  	;
  1591 000009B1 B810000000              	mov	eax, KDATA
  1592 000009B6 8ED8                    	mov	ds, ax
  1593 000009B8 8EC0                    	mov	es, ax
  1594                                  	;
  1595                                  	; 25/08/2014
  1596                                  	;call	rtc_p
  1597                                  	; 23/02/2022
  1598 000009BA FF15[0E070000]          	call	[x_rtci]
  1599                                  	;
  1600                                  	; 22/02/2015 - dsectpm.s
  1601                                  	; [ source: http://wiki.osdev.org/RTC ]
  1602                                  	; read status register C to complete procedure
  1603                                  	;(it is needed to get a next IRQ 8) 
  1604 000009C0 B00C                    	mov	al, 0Ch ; 
  1605 000009C2 E670                    	out	70h, al ; select register C
  1606 000009C4 90                      	nop
  1607 000009C5 E471                    	in	al, 71h ; just throw away contents
  1608                                  	; 22/02/2015
  1609 000009C7 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1610 000009C9 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1611                                  	;
  1612 000009CB EBD3                    	jmp	short iiret	
  1613                                  
  1614                                  	; 22/08/2014
  1615                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1616                                  	; (INT 1Ah)
  1617                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1618                                  time_of_day:
  1619 000009CD E868010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1620 000009D2 726F                            jc      short rtc_retn 
  1621 000009D4 B000                    	mov	al, CMOS_SECONDS
  1622 000009D6 E847010000              	call	CMOS_READ
  1623 000009DB A2[BC620000]            	mov	[time_seconds], al 
  1624 000009E0 B002                    	mov	al, CMOS_MINUTES
  1625 000009E2 E83B010000              	call	CMOS_READ
  1626 000009E7 A2[BD620000]            	mov	[time_minutes], al 
  1627 000009EC B004                    	mov	al, CMOS_HOURS
  1628 000009EE E82F010000              	call	CMOS_READ
  1629 000009F3 A2[BE620000]                    mov     [time_hours], al
  1630 000009F8 B006                    	mov	al, CMOS_DAY_WEEK 
  1631 000009FA E823010000              	call	CMOS_READ
  1632 000009FF A2[BF620000]            	mov	[date_wday], al
  1633 00000A04 B007                     	mov	al, CMOS_DAY_MONTH
  1634 00000A06 E817010000              	call	CMOS_READ
  1635 00000A0B A2[C0620000]            	mov	[date_day], al
  1636 00000A10 B008                    	mov	al, CMOS_MONTH
  1637 00000A12 E80B010000              	call	CMOS_READ
  1638 00000A17 A2[C1620000]            	mov	[date_month], al
  1639 00000A1C B009                    	mov	al, CMOS_YEAR
  1640 00000A1E E8FF000000              	call	CMOS_READ
  1641 00000A23 A2[C2620000]            	mov	[date_year], al
  1642 00000A28 B032                    	mov	al, CMOS_CENTURY
  1643 00000A2A E8F3000000              	call	CMOS_READ
  1644 00000A2F A2[C3620000]            	mov	[date_century], al
  1645                                  	;
  1646 00000A34 B000                    	mov	al, CMOS_SECONDS
  1647 00000A36 E8E7000000              	call 	CMOS_READ
  1648 00000A3B 3A05[BC620000]          	cmp	al, [time_seconds]
  1649 00000A41 758A                    	jne	short time_of_day
  1650                                  
  1651                                  rtc_retn:
  1652 00000A43 C3                      	retn
  1653                                  
  1654                                  rtci_default:
  1655                                  	; 23/02/2022 (Temporary!)
  1656                                  	; (default real time clock handler in multitasking mode)
  1657                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1658 00000A44 FF05[00630000]          	inc	dword [rtc_ticks] ; real time clock counter
  1659                                  			; (not used in anywhere of kernel for now!)
  1660 00000A4A C3                      	retn
  1661                                  
  1662                                  rtc_p:	
  1663                                  	; 27/02/2022
  1664                                  	; 12/02/2022
  1665                                  	; 07/09/2014
  1666                                  	; 29/08/2014
  1667                                  	; 27/08/2014
  1668                                  	; 25/08/2014
  1669                                   	; Print Real Time Clock content
  1670                                  	;
  1671                                  	;
  1672 00000A4B E87DFFFFFF              	call	time_of_day
  1673 00000A50 72F1                    	jc	short rtc_retn
  1674                                  	;
  1675 00000A52 3A05[8A5E0000]          	cmp	al, [ptime_seconds]
  1676 00000A58 74E9                            je      short rtc_retn ; 29/08/2014
  1677                                  	;
  1678 00000A5A A2[8A5E0000]            	mov	[ptime_seconds], al
  1679                                  	;
  1680 00000A5F A0[C3620000]            	mov	al, [date_century]
  1681 00000A64 E8EC000000              	call	bcd_to_ascii
  1682 00000A69 66A3[575E0000]          	mov	[datestr+6], ax
  1683 00000A6F A0[C2620000]            	mov	al, [date_year]
  1684 00000A74 E8DC000000              	call	bcd_to_ascii
  1685 00000A79 66A3[595E0000]          	mov	[datestr+8], ax
  1686 00000A7F A0[C1620000]            	mov	al, [date_month]
  1687 00000A84 E8CC000000              	call	bcd_to_ascii
  1688 00000A89 66A3[545E0000]          	mov	[datestr+3], ax
  1689 00000A8F A0[C0620000]            	mov	al, [date_day]
  1690 00000A94 E8BC000000              	call	bcd_to_ascii
  1691 00000A99 66A3[515E0000]          	mov	[datestr], ax
  1692                                  	;
  1693 00000A9F 0FB61D[BF620000]        	movzx	ebx, byte [date_wday]
  1694 00000AA6 C0E302                  	shl 	bl, 2
  1695 00000AA9 81C3[6A5E0000]          	add	ebx, daytmp
  1696 00000AAF 8B03                    	mov	eax, [ebx]
  1697 00000AB1 A3[5C5E0000]            	mov	[daystr], eax
  1698                                  	;
  1699 00000AB6 A0[BE620000]            	mov	al, [time_hours]
  1700 00000ABB E895000000              	call	bcd_to_ascii
  1701 00000AC0 66A3[605E0000]          	mov	[timestr], ax
  1702 00000AC6 A0[BD620000]            	mov	al, [time_minutes]
  1703 00000ACB E885000000              	call	bcd_to_ascii
  1704 00000AD0 66A3[635E0000]          	mov	[timestr+3], ax
  1705 00000AD6 A0[BC620000]            	mov	al, [time_seconds]
  1706 00000ADB E875000000              	call	bcd_to_ascii
  1707 00000AE0 66A3[665E0000]          	mov	[timestr+6], ax
  1708                                  	;		
  1709 00000AE6 BE[3F5E0000]            	mov	esi, rtc_msg ; message offset
  1710                                  	; 23/02/2015
  1711 00000AEB 52                      	push	edx
  1712 00000AEC 51                      	push	ecx
  1713                                  	; 07/09/2014
  1714                                  	;mov	bx, 2	; Video page 2
  1715                                  	; 27/02/2022
  1716 00000AED 29DB                    	sub	ebx, ebx
  1717 00000AEF B307                    	mov	bl, 7	; Video page 7
  1718                                  prtmsg:
  1719 00000AF1 AC                      	lodsb
  1720 00000AF2 08C0                    	or	al, al
  1721 00000AF4 740D                    	jz	short prtmsg_ok
  1722 00000AF6 56                      	push	esi
  1723                                  	; 27/02/2022
  1724 00000AF7 53                      	push	ebx
  1725                                  	;push	bx
  1726 00000AF8 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1727                                  			; white (F) forecolor
  1728 00000AFA E8BD080000              	call 	write_tty
  1729                                  	;pop	bx
  1730                                  	; 27/02/2022
  1731 00000AFF 5B                      	pop	ebx
  1732 00000B00 5E                      	pop	esi
  1733 00000B01 EBEE                    	jmp	short prtmsg
  1734                                  	;
  1735                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1736                                  	;call	printk
  1737                                  prtmsg_ok:
  1738                                  	; 07/09/2014
  1739                                  	;xor	dx, dx		; column 0, row 0
  1740                                  	; 27/02/2022
  1741 00000B03 31D2                    	xor	edx, edx
  1742 00000B05 E8BC090000              	call	set_cpos	; set cursor position to 0,0 
  1743                                  	; 23/02/2015
  1744 00000B0A 59                      	pop	ecx
  1745 00000B0B 5A                      	pop	edx
  1746 00000B0C C3                      	retn
  1747                                  
  1748                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1749                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1750                                  default_irq7:
  1751                                  	; 27/02/2022
  1752                                  	;push	ax
  1753 00000B0D 50                      	push	eax
  1754 00000B0E B00B                    	mov	al, 0Bh  ; In-Service register
  1755 00000B10 E620                    	out	20h, al
  1756 00000B12 EB00                            jmp short $+2
  1757 00000B14 EB00                    	jmp short $+2
  1758 00000B16 E420                    	in	al, 20h
  1759 00000B18 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1760 00000B1A 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1761 00000B1C B020                            mov     al, 20h ; EOI
  1762 00000B1E E620                    	out	20h, al 
  1763                                  irq7_iret:
  1764                                  	;pop	ax
  1765                                  	; 27/02/2022
  1766 00000B20 58                      	pop	eax
  1767 00000B21 CF                      	iretd
  1768                                  	
  1769                                  	; 22/08/2014
  1770                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1771                                  CMOS_READ:
  1772 00000B22 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1773 00000B23 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1774 00000B25 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1775 00000B26 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1776 00000B28 FA                      	cli		; DISABLE INTERRUPTS
  1777 00000B29 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1778 00000B2B 90                      	nop		; I/O DELAY
  1779 00000B2C E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1780 00000B2E 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1781                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1782                                  		     ; ----- 10/06/85 (test4.asm)
  1783 00000B30 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1784                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1785 00000B32 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1786 00000B34 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1787 00000B36 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1788 00000B38 9D                      	popf	
  1789 00000B39 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1790                                  
  1791                                  	; 22/08/2014
  1792                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1793                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1794 00000B3A 51                      	push	ecx
  1795 00000B3B B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1796                                  		; mov cx, 800	
  1797                                  UPD_10:
  1798 00000B40 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1799 00000B42 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1800 00000B43 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1801 00000B48 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1802 00000B4A 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1803 00000B4C FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1804 00000B4D E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1805 00000B4F 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1806                                  		; xor ax, ax
  1807 00000B51 F9                      	stc				; SET CARRY FOR ERROR
  1808                                  UPD_90:
  1809 00000B52 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1810 00000B53 FA                      	cli				; INTERRUPTS OFF DURING SET
  1811 00000B54 C3                      	retn				; RETURN WITH CY FLAG SET
  1812                                  
  1813                                  bcd_to_ascii:
  1814                                  	; 25/08/2014
  1815                                  	; INPUT ->
  1816                                  	;	al = Packed BCD number
  1817                                  	; OUTPUT ->
  1818                                  	;	ax  = ASCII word/number
  1819                                  	;
  1820                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1821                                  	;
  1822 00000B55 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1823                                  					; AH = AL / 10h
  1824                                  					; AL = AL MOD 10h
  1825 00000B57 660D3030                	or ax,'00'                      ; Make it ASCII based
  1826                                  
  1827 00000B5B 86E0                            xchg ah, al 
  1828                                  	
  1829 00000B5D C3                      	retn	
  1830                                  	
  1831                                  %include 'keyboard.inc' ; 07/03/2015
  1832                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KEYBOARD.INC
  1833                              <1> ; Last Modification: 13/06/2022
  1834                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1835                              <1> ;
  1836                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1837                              <1> 
  1838                              <1> ; 13/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  1839                              <1> ; 23/02/2022 
  1840                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1841                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1842                              <1> ; 30/06/2015
  1843                              <1> ; 11/03/2015
  1844                              <1> ; 28/02/2015
  1845                              <1> ; 25/02/2015
  1846                              <1> ; 20/02/2015
  1847                              <1> ; 18/02/2015
  1848                              <1> ; 03/12/2014
  1849                              <1> ; 07/09/2014
  1850                              <1> ; KEYBOARD INTERRUPT HANDLER
  1851                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1852                              <1> 
  1853                              <1> ;getch:
  1854                              <1> ;	; 18/02/2015
  1855                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1856                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1857                              <1> ;	; routine, later... (multi tasking ability)
  1858                              <1> ;	; 28/02/2015
  1859                              <1> ;	sti	; enable interrupts
  1860                              <1> ;	;
  1861                              <1> ;	;push	esi
  1862                              <1> ;	;push	ebx
  1863                              <1> ;	;xor	ebx, ebx
  1864                              <1> ;	;mov	bl, [ptty]  ; active_page
  1865                              <1> ;	;mov	esi, ebx
  1866                              <1> ;	;shl 	si, 1
  1867                              <1> ;	;add	esi, ttychr
  1868                              <1> ;getch_1:
  1869                              <1> ;	;mov	ax, [esi]
  1870                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1871                              <1> ;	and	ax, ax
  1872                              <1> ;	jz	short getch_2
  1873                              <1> ;	mov	word [ttychr], 0
  1874                              <1> ;	;mov	word [esi], 0
  1875                              <1> ;	;pop	ebx
  1876                              <1> ;	;pop	esi
  1877                              <1> ;	retn
  1878                              <1> ;getch_2:
  1879                              <1> ;	hlt	; not proper for multi tasking!
  1880                              <1> ;		; (temporary halt for now)
  1881                              <1> ;		; 'sleep' on tty 
  1882                              <1> ;		; will (must) be located here		
  1883                              <1> ;	nop
  1884                              <1> ;	jmp	short getch_1
  1885                              <1> 
  1886                              <1> keyb_int:
  1887                              <1> 	; 23/02/2022
  1888                              <1> 	; 30/06/2015
  1889                              <1> 	; 25/02/2015
  1890                              <1> 	; 20/02/2015
  1891                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1892                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1893                              <1> 	; 30/06/2014
  1894                              <1> 	; 10/05/2013	
  1895                              <1>       	; Retro Unix 8086 v1 feature only!
  1896                              <1> 	; 03/03/2014
  1897                              <1> 	
  1898 00000B5E 1E                  <1> 	push	ds
  1899 00000B5F 53                  <1> 	push	ebx
  1900 00000B60 50                  <1> 	push	eax
  1901                              <1> 	;
  1902                              <1> 	; 23/02/2022
  1903 00000B61 9C                  <1> 	pushfd
  1904 00000B62 0E                  <1> 	push	cs
  1905                              <1> 	;mov	ax, KDATA
  1906 00000B63 31C0                <1> 	xor	eax, eax
  1907 00000B65 B010                <1> 	mov	al, KDATA
  1908 00000B67 8ED8                <1> 	mov	ds, ax
  1909                              <1> 	;
  1910                              <1> 	;pushfd
  1911                              <1> 	;push	cs
  1912 00000B69 E810020000          <1> 	call	kb_int   ; int_09h
  1913                              <1> 	;
  1914 00000B6E B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1915                              <1> 	;call	getc
  1916 00000B70 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1917 00000B75 744E                <1> 	jz	short keyb_int4
  1918                              <1> 	;
  1919 00000B77 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1920                              <1> 	;call	getc
  1921 00000B79 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1922                              <1> 	;
  1923                              <1> 	; 20/02/2015
  1924 00000B7E 0FB61D[76620000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1925                              <1> 	;
  1926 00000B85 20C0                <1> 	and 	al, al
  1927 00000B87 751D                <1> 	jnz	short keyb_int1
  1928                              <1> 	;
  1929 00000B89 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1930 00000B8C 7218                <1> 	jb	short keyb_int1
  1931 00000B8E 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1932 00000B91 7713                <1> 	ja	short keyb_int1
  1933                              <1> 	;
  1934 00000B93 88D8                <1> 	mov	al, bl
  1935 00000B95 0468                <1> 	add	al, 68h
  1936 00000B97 38E0                <1> 	cmp	al, ah
  1937 00000B99 7409                <1> 	je	short keyb_int0
  1938 00000B9B 88E0                <1> 	mov	al, ah
  1939 00000B9D 2C68                <1> 	sub	al, 68h
  1940 00000B9F E8370A0000          <1> 	call	tty_sw
  1941                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1942                              <1> keyb_int0: ; 30/06/2015
  1943                              <1> 	;xor	ax, ax
  1944                              <1> 	; 23/02/2022
  1945 00000BA4 31C0                <1> 	xor	eax, eax
  1946                              <1> keyb_int1:
  1947 00000BA6 D0E3                <1> 	shl	bl, 1
  1948 00000BA8 81C3[78620000]      <1> 	add	ebx, ttychr
  1949                              <1> 	;
  1950                              <1> 	;23/02/2022
  1951 00000BAE 09C0                <1> 	or	eax, eax
  1952                              <1> 	;or	ax, ax
  1953 00000BB0 7406                <1> 	jz	short keyb_int2
  1954                              <1> 	;
  1955 00000BB2 66833B00            <1> 	cmp 	word [ebx], 0
  1956 00000BB6 7703                <1>         ja      short keyb_int3 
  1957                              <1> keyb_int2:
  1958 00000BB8 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1959                              <1> 			   ; and scan code of the character
  1960                              <1> 			   ; for current tty (or last tty
  1961                              <1> 			   ; just before tty switch).
  1962                              <1> keyb_int3:
  1963 00000BBB A0[76620000]        <1>         mov     al, [ptty]
  1964 00000BC0 E8493B0000          <1> 	call	wakeup
  1965                              <1> 	;
  1966                              <1> keyb_int4:
  1967 00000BC5 58                  <1> 	pop	eax
  1968 00000BC6 5B                  <1> 	pop	ebx
  1969 00000BC7 1F                  <1> 	pop	ds
  1970 00000BC8 CF                  <1> 	iret
  1971                              <1> 
  1972                              <1> ; 18/02/2015
  1973                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1974                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1975                              <1> ; scancode and ascii code of the character 
  1976                              <1> ; in the tty input (ttychr) buffer. 
  1977                              <1> ; Test procedures must call 'getch' for tty input
  1978                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1979                              <1> ; due to infinite (key press) waiting loop.
  1980                              <1> ; 
  1981                              <1> ; 03/12/2014
  1982                              <1> ; 26/08/2014
  1983                              <1> ; KEYBOARD I/O
  1984                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1985                              <1> 
  1986                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1987                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1988                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1989                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1990                              <1> 
  1991                              <1> int_16h: ; 30/06/2015
  1992                              <1> ;getc:
  1993 00000BC9 9C                  <1> 	pushfd	; 28/08/2014
  1994 00000BCA 0E                  <1> 	push 	cs
  1995 00000BCB E826000000          <1> 	call 	getc_int
  1996 00000BD0 C3                  <1> 	retn
  1997                              <1> 
  1998                              <1> ; 24/12/2021
  1999                              <1> 
  2000                              <1> 	;-----	SHIFT STATUS
  2001                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2002 00000BD1 8A25[A45C0000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2003 00000BD7 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2004                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2005                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2006 00000BDA C0E405              <1>         shl	ah, 5
  2007 00000BDD A0[A45C0000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2008 00000BE2 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2009 00000BE4 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2010 00000BE6 A0[A65C0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2011 00000BEB 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2012 00000BED 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2013                              <1> _K3:
  2014 00000BEF A0[A35C0000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2015 00000BF4 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2016                              <1> 
  2017                              <1> getc_int:
  2018                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2019                              <1> 	; 28/02/2015
  2020                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2021                              <1> 	;	      instead of pc-at bios - 1985-)
  2022                              <1> 	; 28/08/2014 (_k1d)
  2023                              <1> 	; 30/06/2014
  2024                              <1> 	; 03/03/2014
  2025                              <1> 	; 28/02/2014
  2026                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2027                              <1> 	; rombios source code (21/04/1986)
  2028                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2029                              <1> 	;
  2030                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2031                              <1> 	;
  2032                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2033                              <1> 	; KEYBOARD I/O								      :
  2034                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2035                              <1> 	; INPUT									      :
  2036                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2037                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2038                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2039                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2040                              <1> 	;-----------------------------------------------------------------------------:
  2041                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2042                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2043                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2044                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2045                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2046                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2047                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2048                              <1> 	;-----------------------------------------------------------------------------:	
  2049                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2050                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2051                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2052                              <1> 	;-----------------------------------------------------------------------------:	
  2053                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2054                              <1> 	;	      (AL) = 05H                                                      :
  2055                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2056                              <1> 	;		       							      :
  2057                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2058                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2059                              <1> 	;                     --------------------------------------------            :
  2060                              <1> 	;			00H        30.0        10H        7.5                 :
  2061                              <1> 	;			01H        26.7        11H        6.7                 :
  2062                              <1> 	;			02H        24.0        12H        6.0                 :
  2063                              <1> 	;			03H        21.8        13H        5.5                 :
  2064                              <1> 	;			04H        20.0        14H        5.0                 :
  2065                              <1> 	;			05H        18.5        15H        4.6                 :
  2066                              <1> 	;			06H        17.1        16H        4.3                 :
  2067                              <1> 	;			07H        16.0        17H        4.0                 :
  2068                              <1> 	;			08H        15.0        18H        3.7                 :
  2069                              <1> 	;			09H        13.3        19H        3.3                 :
  2070                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2071                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2072                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2073                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2074                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2075                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2076                              <1> 	;									      :
  2077                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2078                              <1> 	;		       							      :
  2079                              <1> 	;                     REGISTER     DELAY                                      :
  2080                              <1> 	;                      VALUE       VALUE                                      :
  2081                              <1> 	;                     ------------------                                      :
  2082                              <1> 	;			00H        250 ms                                     :
  2083                              <1> 	;			01H        500 ms                                     :
  2084                              <1> 	;			02H        750 ms                                     :
  2085                              <1> 	;			03H       1000 ms                                     :
  2086                              <1> 	;-----------------------------------------------------------------------------:
  2087                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2088                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2089                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2090                              <1> 	;		           (CH) = SCAN CODE                                   :
  2091                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2092                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2093                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2094                              <1> 	;-----------------------------------------------------------------------------:		
  2095                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2096                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2097                              <1> 	;-----------------------------------------------------------------------------:
  2098                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2099                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2100                              <1> 	;-----------------------------------------------------------------------------:	
  2101                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2102                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2103                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2104                              <1> 	; OUTPUT					                              :
  2105                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2106                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2107                              <1> 	;------------------------------------------------------------------------------
  2108                              <1> 	
  2109 00000BF6 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2110 00000BF7 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2111 00000BF8 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2112                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2113 00000BF9 66BB1000            <1>         mov     bx, KDATA 
  2114 00000BFD 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2115 00000BFF 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2116 00000C01 742D                <1> 	jz	short _K1		; ASCII_READ
  2117 00000C03 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2118 00000C05 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2119 00000C07 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2120 00000C09 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2121 00000C0B FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2122 00000C0D 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2123 00000C0F 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2124 00000C12 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2125                              <1> _KIO1:	
  2126 00000C14 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2127 00000C17 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2128 00000C19 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2129 00000C1B 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2130 00000C1D FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2131 00000C1F 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2132                              <1> _KIO_EXIT:
  2133                              <1> 	;pop	ecx			; RECOVER REGISTER
  2134 00000C21 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2135 00000C22 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2136 00000C23 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2137                              <1> 
  2138                              <1> 	;-----	ASCII CHARACTER
  2139                              <1> _K1E:	
  2140 00000C24 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2141 00000C29 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2142 00000C2E EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2143                              <1> _K1:	
  2144 00000C30 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2145 00000C35 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2146 00000C3A 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2147                              <1> _K1A:
  2148 00000C3C EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2149                              <1> 
  2150                              <1> 	;-----	ASCII STATUS
  2151                              <1> _K2E:	
  2152 00000C3E E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2153 00000C43 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2154 00000C45 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2155 00000C46 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2156 00000C4B EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2157                              <1> _K2:	
  2158 00000C4D E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2159 00000C52 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2160 00000C54 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2161 00000C55 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2162 00000C5A 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2163 00000C5C 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2164 00000C5D E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2165 00000C62 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2166                              <1> _K2A:
  2167 00000C64 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2168                              <1> _K2B:
  2169                              <1> 	;pop	ecx			; RECOVER REGISTER
  2170 00000C65 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2171 00000C66 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2172 00000C67 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2173                              <1> 
  2174                              <1> ; 24/12/2021
  2175                              <1> ;	;-----	SHIFT STATUS
  2176                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2177                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2178                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2179                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2180                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2181                              <1> ;       shl	ah, 5
  2182                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2183                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2184                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2185                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2186                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2187                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2188                              <1> ;_K3:
  2189                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2190                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2191                              <1> 
  2192                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2193                              <1> _K300:
  2194 00000C6A 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2195 00000C6C 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2196 00000C6E F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2197 00000C71 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2198 00000C73 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2199 00000C76 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2200 00000C78 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2201 00000C7A E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2202                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2203                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2204 00000C7F C0E705              <1> 	shl	bh, 5
  2205 00000C82 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2206 00000C84 08F8                <1> 	or	al, bh			; AND DELAY
  2207 00000C86 E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2208 00000C8B EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2209                              <1> 
  2210                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2211                              <1> _K500:
  2212 00000C8D 56                  <1> 	push	esi			; SAVE SI (esi)
  2213 00000C8E FA                  <1> 	cli				; 
  2214 00000C8F 8B1D[B45C0000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2215 00000C95 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2216 00000C97 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2217 00000C9C 3B1D[B05C0000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2218 00000CA2 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2219 00000CA4 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2220 00000CA7 891D[B45C0000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2221 00000CAD 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2222 00000CAF EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2223                              <1> _K502:
  2224 00000CB1 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2225                              <1> _K504:
  2226 00000CB3 FB                  <1> 	sti				
  2227 00000CB4 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2228 00000CB5 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2229                              <1> 
  2230                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2231                              <1> _K1S:
  2232 00000CBA FA                  <1> 	cli	; 03/12/2014
  2233 00000CBB 8B1D[B05C0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2234 00000CC1 3B1D[B45C0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2235                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2236 00000CC7 750F                <1> 	jne	short _k1x ; 03/12/2014
  2237                              <1> 	;
  2238                              <1> 	; 03/12/2014
  2239                              <1> 	; 28/08/2014
  2240                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2241                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2242                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2243                              <1> _K1T:                                   ; ASCII READ
  2244 00000CC9 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2245 00000CCA 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2246                              <1> _K1U:	
  2247 00000CCB FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2248 00000CCC 8B1D[B05C0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2249 00000CD2 3B1D[B45C0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2250                              <1> _k1x:
  2251 00000CD8 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2252 00000CD9 9C                  <1> 	pushf				; SAVE FLAGS
  2253 00000CDA E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2254 00000CDF 8A1D[A55C0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2255 00000CE5 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2256 00000CE7 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2257 00000CEA 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2258 00000CEC E86A060000          <1> 	call	SND_LED1
  2259 00000CF1 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2260                              <1> _K1V:
  2261 00000CF2 9D                  <1> 	popf				; RESTORE FLAGS
  2262 00000CF3 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2263 00000CF4 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2264                              <1> 	;
  2265 00000CF6 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2266 00000CF9 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2267 00000CFE 891D[B05C0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2268 00000D04 C3                  <1> 	retn				; RETURN
  2269                              <1> 
  2270                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2271                              <1> _K2S:
  2272 00000D05 FA                  <1> 	cli				; INTERRUPTS OFF
  2273 00000D06 8B1D[B05C0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2274 00000D0C 3B1D[B45C0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2275 00000D12 668B03              <1> 	mov	ax, [ebx]
  2276 00000D15 9C                  <1> 	pushf				; SAVE FLAGS
  2277                              <1> 	;push	ax			; SAVE CODE
  2278                              <1> 	; 24/12/2021
  2279 00000D16 50                  <1> 	push	eax
  2280 00000D17 E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2281 00000D1C 8A1D[A55C0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2282 00000D22 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2283 00000D24 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2284 00000D27 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2285 00000D29 E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2286                              <1> _K2T:
  2287                              <1> 	;pop	ax			; RESTORE CODE
  2288                              <1> 	; 24/12/2021
  2289 00000D2E 58                  <1> 	pop	eax
  2290 00000D2F 9D                  <1> 	popf				; RESTORE FLAGS
  2291 00000D30 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2292 00000D31 C3                  <1> 	retn				; RETURN
  2293                              <1> 
  2294                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2295                              <1> _KIO_E_XLAT:
  2296 00000D32 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2297 00000D34 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2298 00000D36 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2299 00000D38 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2300 00000D3A 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2301                              <1> _KIO_E_RET:				
  2302 00000D3C C3                  <1> 	retn				; GO BACK
  2303                              <1> 
  2304                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2305                              <1> _KIO_S_XLAT:
  2306 00000D3D 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2307 00000D40 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2308 00000D42 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2309 00000D44 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2310 00000D46 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2311 00000D48 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2312 00000D4A B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2313                              <1> _kio_ret: ; 03/12/2014
  2314 00000D4C F8                  <1> 	clc
  2315 00000D4D C3                  <1> 	retn
  2316                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2317                              <1> _KIO_S1:				
  2318 00000D4E B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2319                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2320 00000D50 C3                  <1> 	retn
  2321                              <1> _KIO_S2:		
  2322 00000D51 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2323 00000D54 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2324 00000D56 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2325 00000D58 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2326 00000D5A 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2327 00000D5C 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2328 00000D5E EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2329                              <1> _KIO_S3:
  2330 00000D60 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2331                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2332 00000D62 75E8                <1> 	jne	short _kio_ret
  2333 00000D64 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2334 00000D66 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2335 00000D68 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2336                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2337                              <1> _KIO_USE:
  2338                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2339 00000D6A C3                  <1> 	retn				; RETURN	
  2340                              <1> _KIO_DIS:
  2341 00000D6B F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2342 00000D6C C3                  <1> 	retn				; RETURN
  2343                              <1> 
  2344                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2345                              <1> _K4:    
  2346 00000D6D 43                  <1> 	inc     ebx
  2347 00000D6E 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2348 00000D6F 3B1D[AC5C0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2349                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2350 00000D75 7206                <1> 	jb	short _K5
  2351 00000D77 8B1D[A85C0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2352                              <1> _K5:
  2353 00000D7D C3                  <1> 	retn
  2354                              <1> 
  2355                              <1> ; 20/02/2015
  2356                              <1> ; 05/12/2014
  2357                              <1> ; 26/08/2014
  2358                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2359                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2360                              <1> ;
  2361                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2362                              <1> ; rombios source code (06/10/1985)
  2363                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2364                              <1> 
  2365                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2366                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2367                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2368                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2369                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2370                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2371                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2372                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2373                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2374                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2375                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2376                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2377                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2378                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2379                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2380                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2381                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2382                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2383                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2384                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2385                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2386                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2387                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2388                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2389                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2390                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2391                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2392                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2393                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2394                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2395                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2396                              <1> F11_M		equ	87		; F11 KEY MAKE
  2397                              <1> F12_M		equ	88		; F12 KEY MAKE
  2398                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2399                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2400                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2401                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2402                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2403                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2404                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2405                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2406                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2407                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2408                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2409                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2410                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2411                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2412                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2413                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2414                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2415                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2416                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2417                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2418                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2419                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2420                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2421                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2422                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2423                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2424                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2425                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2426                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2427                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2428                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2429                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2430                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2431                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2432                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2433                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2434                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2435                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2436                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2437                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2438                              <1> ;
  2439                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2440                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2441                              <1> INTA00		equ	020h		; 8259 PORT
  2442                              <1> 
  2443                              <1> 
  2444                              <1> kb_int:
  2445                              <1> 
  2446                              <1> ; 13/06/2022
  2447                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2448                              <1> ; 17/10/2015 ('ctrlbrk') 
  2449                              <1> ; 05/12/2014
  2450                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2451                              <1> 	;	      instead of pc-at bios - 1985-)
  2452                              <1> ; 26/08/2014
  2453                              <1> ;
  2454                              <1> ; 03/06/86  KEYBOARD BIOS
  2455                              <1> ;
  2456                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2457                              <1> ;										;
  2458                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2459                              <1> ;										;
  2460                              <1> ;--------------------------------------------------------------------------------
  2461                              <1> 
  2462                              <1> KB_INT_1:
  2463 00000D7E FB                  <1> 	sti				; ENABLE INTERRUPTS
  2464                              <1> 	;push	ebp
  2465 00000D7F 50                  <1> 	push	eax
  2466 00000D80 53                  <1> 	push	ebx
  2467 00000D81 51                  <1> 	push	ecx
  2468 00000D82 52                  <1> 	push	edx
  2469 00000D83 56                  <1> 	push	esi
  2470 00000D84 57                  <1> 	push	edi
  2471 00000D85 1E                  <1> 	push	ds
  2472 00000D86 06                  <1> 	push	es
  2473 00000D87 FC                  <1> 	cld				; FORWARD DIRECTION
  2474 00000D88 66B81000            <1> 	mov	ax, KDATA
  2475 00000D8C 8ED8                <1> 	mov	ds, ax
  2476 00000D8E 8EC0                <1> 	mov	es, ax
  2477                              <1> 	;
  2478                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2479 00000D90 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2480 00000D92 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2481 00000D97 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2482 00000D98 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2483                              <1> KB_INT_01:
  2484 00000D9D E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2485 00000D9F A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2486 00000DA1 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2487                              <1> 	;
  2488                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2489 00000DA3 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2490                              <1> 	;
  2491                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2492                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2493                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2494                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2495                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2496                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2497                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2498                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2499                              <1> 	;
  2500                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2501                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2502 00000DA5 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2503 00000DA6 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2504 00000DA8 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2505                              <1> 	;
  2506                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2507 00000DAA 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2508 00000DAC 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2509                              <1> 	;
  2510                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2511 00000DAE FA                  <1> 	cli				; DISABLE INTERRUPTS
  2512 00000DAF 800D[A55C0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2513 00000DB6 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2514                              <1> 	;
  2515                              <1> 	;-----	RESEND THE LAST BYTE
  2516                              <1> KB_INT_4:
  2517 00000DBB FA                  <1> 	cli				; DISABLE INTERRUPTS
  2518 00000DBC 800D[A55C0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2519 00000DC3 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2520                              <1> 	;
  2521                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2522                              <1> KB_INT_2:
  2523                              <1> 	;push 	ax			; SAVE DATA IN
  2524                              <1> 	; 24/12/2021
  2525 00000DC8 50                  <1> 	push	eax
  2526 00000DC9 E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2527 00000DCE 8A1D[A55C0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2528 00000DD4 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2529 00000DD6 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2530 00000DD9 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2531 00000DDB E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2532                              <1> UP0:
  2533                              <1> 	;pop	ax			; RESTORE DATA IN
  2534                              <1> 	; 24/12/2021
  2535 00000DE0 58                  <1> 	pop	eax
  2536                              <1> ;------------------------------------------------------------------------
  2537                              <1> ;	START OF KEY PROCESSING						;
  2538                              <1> ;------------------------------------------------------------------------
  2539 00000DE1 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2540                              <1> 	;
  2541                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2542 00000DE3 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2543                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2544                              <1> 	; 24/12/2021
  2545 00000DE5 7505                <1> 	jne	short K16
  2546 00000DE7 E9E9040000          <1> 	jmp	K62
  2547                              <1> K16:	
  2548 00000DEC 8A3D[A65C0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2549                              <1> 	;
  2550                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2551 00000DF2 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2552 00000DF5 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2553 00000DF7 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2554 00000DF9 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2555 00000DFB 7507                <1> 	jne	short RST_RD_ID
  2556 00000DFD 800D[A65C0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2557                              <1> RST_RD_ID:
  2558 00000E04 8025[A65C0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2559 00000E0B EB27                <1>         jmp    short ID_EX		; AND EXIT
  2560                              <1> 	; 24/12/2021
  2561                              <1> 	;jmp	K26
  2562                              <1> 	;
  2563                              <1> TST_ID_2:
  2564 00000E0D 8025[A65C0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2565 00000E14 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2566 00000E16 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2567 00000E18 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2568 00000E1A 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2569                              <1> 	; 24/12/2021
  2570                              <1> 	;jne	K26
  2571                              <1> 	;
  2572                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2573 00000E1C F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2574 00000E1F 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2575 00000E21 800D[A35C0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2576 00000E28 E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2577                              <1> KX_BIT:
  2578 00000E2D 800D[A65C0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2579 00000E34 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2580                              <1> 	;
  2581                              <1> NOT_ID:
  2582 00000E39 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2583 00000E3B 750E                <1> 	jne	short TEST_E1
  2584 00000E3D 800D[A65C0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2585 00000E44 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2586                              <1> 	; 24/12/2021
  2587 00000E46 E9DA010000          <1> 	jmp	K26A	
  2588                              <1> TEST_E1:	
  2589 00000E4B 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2590 00000E4D 750C                <1> 	jne	short NOT_HC
  2591 00000E4F 800D[A65C0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2592 00000E56 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2593                              <1> 	;
  2594                              <1> NOT_HC:
  2595 00000E5B 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2596 00000E5D F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2597 00000E60 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2598                              <1> 	;
  2599 00000E62 BF[8E5B0000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2600 00000E67 AE                  <1> 	scasb
  2601                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2602                              <1> 	; 24/12/2021
  2603 00000E68 7458                <1> 	je	short K16B
  2604 00000E6A AE                  <1> 	scasb
  2605 00000E6B 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2606 00000E6D EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2607                              <1> 	; 24/12/2021
  2608                              <1> 	;jmp	K26
  2609                              <1> 	;
  2610                              <1> NOT_LC_E0:
  2611 00000E6F F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2612 00000E72 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2613 00000E74 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2614 00000E79 BF[8C5B0000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2615 00000E7E F2AE                <1> 	repne	scasb			; CHECK IT
  2616 00000E80 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2617                              <1> 	; 24/12/2021
  2618                              <1> 	;je	K26A			
  2619                              <1> 	;
  2620 00000E82 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2621 00000E84 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2622                              <1> 	; 24/12/2021
  2623                              <1> 	;jne	K26
  2624 00000E86 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2625 00000E89 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2626                              <1> 	; 24/12/2021
  2627                              <1> 	;jnz	K26
  2628                              <1>         ; 20/02/2015 
  2629 00000E8B F605[A45C0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2630 00000E92 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2631                              <1> 	; 24/12/2021
  2632                              <1> 	;jnz	K26
  2633 00000E94 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2634                              <1> 	;
  2635                              <1> 	;-----	TEST FOR SYSTEM KEY
  2636                              <1> T_SYS_KEY:
  2637 00000E99 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2638 00000E9B 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2639                              <1> 	;
  2640 00000E9D F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2641 00000EA0 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2642                              <1> 	;
  2643 00000EA2 F605[A45C0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2644 00000EA9 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2645                              <1> 	;jnz	K26			
  2646                              <1> 	;
  2647 00000EAB 800D[A45C0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2648 00000EB2 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2649 00000EB4 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2650                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2651 00000EB6 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2652 00000EB8 E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2653                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2654                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2655                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2656                              <1> 	;INT	15H			; USER INTERRUPT	
  2657 00000EBD E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2658                              <1> 	;
  2659 00000EC2 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2660                              <1> 	;
  2661                              <1> K16C:
  2662 00000EC7 8025[A45C0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2663 00000ECE B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2664 00000ED0 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2665                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2666                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2667                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2668                              <1> 	;
  2669                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2670                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2671                              <1> 	;INT	15H			; USER INTERRUPT
  2672                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2673                              <1> 	;
  2674 00000ED2 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2675                              <1> 	;
  2676                              <1> 	;-----	TEST FOR SHIFT KEYS
  2677                              <1> K16A:
  2678 00000ED7 8A1D[A35C0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2679 00000EDD BF[885B0000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2680 00000EE2 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2681 00000EE7 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2682 00000EE9 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2683                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2684                              <1> 	; 24/12/2021
  2685 00000EEB 7405                <1> 	je	short K17
  2686 00000EED E914010000          <1> 	jmp	K25
  2687                              <1> 	;
  2688                              <1> 	;------	SHIFT KEY FOUND
  2689                              <1> K17:
  2690 00000EF2 81EF[895B0000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2691 00000EF8 8AA7[905B0000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2692 00000EFE B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2693 00000F00 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2694                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2695                              <1> 	; 24/12/2021
  2696 00000F02 7405                <1> 	jz	short K17C
  2697 00000F04 E999000000          <1> 	jmp	K23
  2698                              <1> 	;
  2699                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2700                              <1> K17C:
  2701 00000F09 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2702 00000F0C 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2703                              <1> 	;
  2704                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2705 00000F0E 0825[A35C0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2706 00000F14 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2707 00000F16 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2708                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2709                              <1> 	; 24/12/2021
  2710 00000F18 E901010000          <1> 	jmp	K26
  2711                              <1> K17D:
  2712 00000F1D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2713 00000F20 740B                <1> 	jz 	short K17E		; NO, JUMP
  2714 00000F22 0825[A65C0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2715 00000F28 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2716                              <1> K17E:
  2717 00000F2D D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2718 00000F2F 0825[A45C0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2719 00000F35 E9E4000000          <1> 	jmp	K26
  2720                              <1> 	;
  2721                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2722                              <1> K18:					; SHIFT-TOGGLE
  2723 00000F3A F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2724 00000F3D 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2725                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2726                              <1> 	; 24/12/2021
  2727 00000F3F E9C2000000          <1> 	jmp	K25
  2728                              <1> K18A:
  2729 00000F44 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2730 00000F46 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2731 00000F48 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2732 00000F4B 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2733                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2734                              <1> 	; 24/12/2021
  2735 00000F4D E9B4000000          <1> 	jmp	K25
  2736                              <1> K18B:
  2737 00000F52 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2738 00000F55 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2739                              <1> K19:	
  2740 00000F57 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2741 00000F5A 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2742 00000F5C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2743 00000F5F 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2744                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2745 00000F61 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2746 00000F63 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2747                              <1> K21:					; MIGHT BE NUMERIC
  2748 00000F68 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2749 00000F6B 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2750                              <1> 	;
  2751                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2752 00000F6D 8425[A45C0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2753                              <1> 	;jnz	K26
  2754                              <1> 	; 24/12/2021
  2755 00000F73 7405                <1> 	jz	short K22A
  2756 00000F75 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2757                              <1> K22A:
  2758 00000F7A 0825[A45C0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2759 00000F80 3025[A35C0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2760                              <1> 	;
  2761                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2762 00000F86 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2763 00000F89 7407                <1> 	jz	short K22B		; GO IF NOT
  2764                              <1> 	;
  2765                              <1> 	; 24/12/2021
  2766                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2767 00000F8B 50                  <1> 	push	eax
  2768 00000F8C E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2769                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2770 00000F91 58                  <1> 	pop	eax
  2771                              <1> K22B:
  2772 00000F92 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2773                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2774                              <1> 	; 24/12/2021
  2775 00000F94 7405                <1> 	je	short K22C
  2776 00000F96 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2777                              <1> K22C:
  2778 00000F9B 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2779 00000F9D E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2780                              <1> 	;
  2781                              <1> 	;-----	BREAK SHIFT FOUND
  2782                              <1> K23:					; BREAK-SHIFT-FOUND
  2783 00000FA2 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2784 00000FA5 F6D4                <1> 	not	ah			; INVERT MASK
  2785 00000FA7 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2786 00000FA9 2025[A35C0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2787 00000FAF 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2788 00000FB2 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2789                              <1> 	;
  2790 00000FB4 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2791 00000FB7 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2792 00000FB9 2025[A65C0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2793 00000FBF EB08                <1> 	jmp	short K23B		; CONTINUE
  2794                              <1> K23A:
  2795 00000FC1 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2796 00000FC3 2025[A45C0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2797                              <1> K23B:
  2798 00000FC9 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2799 00000FCB A0[A65C0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2800 00000FD0 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2801 00000FD2 0A05[A45C0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2802 00000FD8 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2803 00000FDA 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2804 00000FDC 0805[A35C0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2805 00000FE2 88E0                <1> 	mov	al, ah
  2806                              <1> K23D:
  2807 00000FE4 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2808 00000FE6 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2809                              <1> 	;	
  2810                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2811 00000FE8 A0[A75C0000]        <1> 	mov	al, [ALT_INPUT]
  2812 00000FED B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2813 00000FEF 8825[A75C0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2814 00000FF5 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2815 00000FF7 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2816 00000FF9 E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2817                              <1> 	;
  2818                              <1> K24:					; BREAK-TOGGLE
  2819 00000FFE 2025[A45C0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2820 00001004 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2821                              <1> 	;
  2822                              <1> 	;-----	TEST FOR HOLD STATE
  2823                              <1> 					; AL, AH = SCAN CODE
  2824                              <1> K25:					; NO-SHIFT-FOUND
  2825 00001006 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2826 00001008 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2827 0000100A F605[A45C0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2828 00001011 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2829 00001013 3C45                <1> 	cmp	al, NUM_KEY
  2830 00001015 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2831 00001017 8025[A45C0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2832                              <1> 	;
  2833                              <1> K26:
  2834 0000101E 8025[A65C0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2835                              <1> K26A:					; INTERRUPT-RETURN
  2836 00001025 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2837 00001026 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2838 00001028 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2839                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2840 0000102A B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2841 0000102C E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2842                              <1> K27A:
  2843 00001031 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2844 00001032 07                  <1> 	pop	es			; RESTORE REGISTERS
  2845 00001033 1F                  <1> 	pop	ds
  2846 00001034 5F                  <1> 	pop	edi
  2847 00001035 5E                  <1> 	pop	esi
  2848 00001036 5A                  <1> 	pop	edx
  2849 00001037 59                  <1> 	pop	ecx
  2850 00001038 5B                  <1> 	pop	ebx
  2851 00001039 58                  <1> 	pop	eax
  2852                              <1> 	;pop	ebp
  2853 0000103A CF                  <1> 	iret				; RETURN
  2854                              <1> 
  2855                              <1> 	;-----	NOT IN	HOLD STATE
  2856                              <1> K28:					; NO-HOLD-STATE
  2857 0000103B 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2858 0000103D 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2859                              <1> 	;
  2860 0000103F F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2861 00001042 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2862                              <1>         ; 24/12/2021
  2863                              <1> 	;jz      K38
  2864                              <1> 	;
  2865 00001044 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2866 00001047 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2867                              <1> 	; 28/02/2015
  2868 00001049 F605[A45C0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2869 00001050 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2870                              <1> 	; 24/12/2021
  2871                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2872                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2873 00001052 E9CD000000          <1> K28A:	jmp	K38
  2874                              <1> 	;
  2875                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2876                              <1> K29:					; TEST-RESET
  2877 00001057 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2878 0000105A 740B                <1> 	jz	short K31		; NO_RESET
  2879 0000105C 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2880 0000105E 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2881                              <1> 	;
  2882                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2883                              <1>  	; 26/08/2014
  2884                              <1> cpu_reset:
  2885                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2886                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2887 00001060 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2888 00001062 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2889                              <1> khere:
  2890 00001064 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2891 00001065 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2892                              <1> 
  2893                              <1> 	;
  2894                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2895                              <1> K31:					; NO-RESET
  2896 00001067 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2897 00001069 7507                <1> 	jne	short K311		; NOT THERE
  2898 0000106B B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2899 0000106D E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2900                              <1> K311:
  2901 00001072 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2902 00001074 7509                <1> 	jne	short K312		; NOT THERE
  2903 00001076 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2904 0000107A E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2905                              <1> K312:
  2906 0000107F 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2907 00001081 7471                <1>         je	short K37B              ; GO PROCESS
  2908 00001083 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2909 00001085 746D                <1>         je	short K37B              ; GO PROCESS
  2910                              <1> 	;
  2911                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2912                              <1> K32:					; ALT-KEY-PAD
  2913 00001087 BF[645B0000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2914 0000108C B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2915 00001091 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2916 00001093 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2917 00001095 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2918                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2919                              <1> 	; 24/12/2021
  2920 00001098 751C                <1> 	jnz	short K32B
  2921 0000109A 81EF[655B0000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2922 000010A0 A0[A75C0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2923 000010A5 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2924 000010A7 F6E4                <1> 	mul	ah
  2925 000010A9 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2926 000010AC A2[A75C0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2927                              <1> K32A:
  2928 000010B1 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2929                              <1> K32B:
  2930                              <1> 	; 24/12/2021
  2931 000010B6 EB66                <1> 	jmp	K37C
  2932                              <1> 	;
  2933                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2934                              <1> K33:					; NO-ALT-KEYPAD
  2935 000010B8 C605[A75C0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2936 000010BF B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2937 000010C4 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2938 000010C6 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2939                              <1> 	;
  2940                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2941                              <1> K34:					; ALT-TOP-ROW
  2942 000010C8 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2943 000010CA 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2944 000010CC 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2945 000010CE 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2946 000010D0 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2947 000010D3 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2948                              <1> 	;
  2949                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2950                              <1> K35:					; ALT-FUNCTION
  2951 000010D5 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2952 000010D7 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2953 000010D9 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2954 000010DB 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2955 000010DD 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2956 000010E0 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2957                              <1> K35A:
  2958 000010E2 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2959 000010E5 7425                <1> 	jz	short K37		; NO, JUMP
  2960 000010E7 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2961 000010E9 7510                <1>         jne     short K35B              ; NOT THERE
  2962 000010EB 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2963 000010EF E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  2964                              <1> K37B:
  2965 000010F4 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2966 000010F6 E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2967                              <1> K35B:
  2968 000010FB 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2969 000010FD 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2970 000010FF 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2971 00001101 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2972                              <1>         ; 24/12/2021
  2973                              <1> 	;jne	K26
  2974 00001103 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2975 00001107 E998010000          <1> 	jmp	K57			; BUFFER FILL
  2976                              <1> K37:
  2977 0000110C 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2978 0000110E 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2979 00001110 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2980 00001112 779D                <1>         ja	short K32A		; IF SO, IGNORE
  2981                              <1> 	; 13/06/2022
  2982                              <1>         ;ja	K26
  2983 00001114 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2984                              <1> K37A:
  2985 00001117 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2986 00001119 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2987                              <1> K37C:
  2988 0000111E 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2989 00001120 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2990 00001122 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2991                              <1> 	;
  2992                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2993                              <1> K38:					; NOT-ALT-SHIFT
  2994                              <1> 					; BL STILL HAS SHIFT FLAGS
  2995 00001124 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2996 00001127 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2997                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2998                              <1> 	; 24/12/2021
  2999 00001129 E9AB000000          <1> 	jmp	K44
  3000                              <1> 	;
  3001                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3002                              <1> 	;-----	TEST FOR BREAK
  3003                              <1> K38A:
  3004 0000112E 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3005 00001130 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3006 00001132 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3007 00001135 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3008 00001137 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3009 0000113A 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3010                              <1> K38B:
  3011 0000113C 8B1D[B05C0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3012 00001142 891D[B45C0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3013 00001148 C605[A25C0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3014                              <1> 	;
  3015                              <1> 	;-----	ENABLE KEYBOARD
  3016 0000114F B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3017 00001151 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3018                              <1> 	;
  3019                              <1> 	; CTRL+BREAK code here !!!
  3020                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3021                              <1> 	; 17/10/2015	
  3022 00001156 E8A5190000          <1> 	call	ctrlbrk ; control+break subroutine
  3023                              <1> 	;
  3024                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3025                              <1> 	; 24/12/2021
  3026 0000115B 29C0                <1> 	sub	eax, eax
  3027 0000115D E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3028                              <1> 	;
  3029                              <1> 	;-----	TEST FOR PAUSE
  3030                              <1> K39:					; NO_BREAK
  3031 00001162 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3032 00001165 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3033 00001167 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3034 00001169 7533                <1> 	jne	short K41		; NO-PAUSE
  3035                              <1> K39P:
  3036 0000116B 800D[A45C0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3037                              <1> 	;
  3038                              <1> 	;-----	ENABLE KEYBOARD
  3039 00001172 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3040 00001174 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3041                              <1> K39A:
  3042 00001179 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3043 0000117B E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3044                              <1> 	;
  3045                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3046 0000117D 803D[A05C0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3047 00001184 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3048 00001186 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3049 0000118A A0[A15C0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3050 0000118F EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3051                              <1> 	;
  3052                              <1> K40:					; PAUSE-LOOP
  3053 00001190 F605[A45C0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3054 00001197 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3055                              <1> 	;
  3056 00001199 E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3057                              <1>         ;
  3058                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3059                              <1> K41:					; NO-PAUSE
  3060 0000119E 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3061 000011A0 7513                <1> 	jne	short K42		; NOT-KEY-55
  3062 000011A2 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3063 000011A5 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3064 000011A7 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3065 000011AA 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3066                              <1> K41A:	
  3067 000011AC 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3068 000011B0 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3069                              <1> 	;
  3070                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3071                              <1> K42:					; NOT-KEY-55
  3072 000011B5 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3073 000011B7 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3074 000011B9 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3075 000011BB 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3076 000011BD F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3077 000011C0 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3078 000011C2 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3079 000011C6 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3080                              <1> K42A:
  3081                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3082 000011CB 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3083                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3084                              <1> 	;;jb	K56 ; 20/02/2015
  3085                              <1> 	;;jmp	K64 ; 20/02/2015
  3086                              <1> K42B:
  3087 000011CD BB[985B0000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3088                              <1> 	;;jmp	K64
  3089                              <1> 	;jb	K56 ;; 20/02/2015	
  3090                              <1> 	; 24/12/2021
  3091 000011D2 7267                <1> 	jb	short K45F
  3092 000011D4 E9B9000000          <1> 	jmp	K64	
  3093                              <1>         ;
  3094                              <1> 	;-----	NOT IN CONTROL SHIFT
  3095                              <1> K44:					; NOT-CTL-SHIFT
  3096 000011D9 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3097 000011DB 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3098 000011DD F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3099 000011E0 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3100 000011E2 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3101 000011E5 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3102 000011E7 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3103                              <1> K44A:
  3104 000011E9 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3105 000011EC 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3106                              <1> 	;
  3107                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3108                              <1> K44B:
  3109 000011EE B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3110 000011F0 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3111 000011F5 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3112 000011F7 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3113                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3114                              <1> 	;PUSH 	BP			; SAVE POINTER
  3115                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3116                              <1> 	;POP	BP			; RESTORE POINTER
  3117 000011F9 8025[A65C0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3118 00001200 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3119                              <1> 	;
  3120                              <1> 	;-----	HANDLE IN-CORE KEYS
  3121                              <1> K45:					; NOT-PRINT-SCREEN
  3122 00001205 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3123 00001207 7734                <1> 	ja	short K46		; JUMP IF NOT
  3124 00001209 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3125 0000120B 7505                <1> 	jne	short K45A		; NO, JUMP
  3126 0000120D F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3127 00001210 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3128                              <1> K45A:
  3129 00001212 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3130 00001217 BF[6E5B0000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3131 0000121C F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3132                              <1> 		; 20/02/2015
  3133 0000121E 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3134                              <1> 	;
  3135 00001220 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3136 00001223 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3137                              <1> K45B:
  3138 00001225 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3139 00001228 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3140                              <1> 					; NO, LOWERCASE
  3141                              <1> K45C:
  3142 0000122A BB[F05B0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3143 0000122F EB51                <1> 	jmp	short K56	
  3144                              <1> K45D:					; ALMOST-CAPS-STATE
  3145 00001231 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3146 00001234 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3147                              <1> K45E:
  3148 00001236 BB[485C0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3149 0000123B EB45                <1> K45F:	jmp	short K56
  3150                              <1> 	;
  3151                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3152                              <1> K46:					; NOT IN-CORE AREA
  3153 0000123D 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3154                              <1> 	;ja	short K47		; JUMP IF NOT
  3155                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3156 0000123F 7635                <1> 	jna	short K53		
  3157                              <1> 	;
  3158                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3159                              <1> K47:					; NOT F1 - F10
  3160 00001241 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3161 00001243 772D                <1> 	ja	short K52		; JUMP IF NOT
  3162                              <1> 	;
  3163                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3164                              <1> K48:
  3165 00001245 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3166 00001247 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3167 00001249 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3168 0000124B 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3169 0000124D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3170 00001250 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3171                              <1> 	;		
  3172 00001252 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3173 00001255 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3174 00001257 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3175                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3176 0000125A 75DA                <1> 	jnz	short K45E
  3177                              <1> 	;
  3178                              <1> 	;-----	BASE CASE FOR KEYPAD
  3179                              <1> K49:					
  3180 0000125C 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3181 0000125E 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3182 00001260 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3183 00001262 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3184                              <1> K49A:
  3185 00001264 BB[F05B0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3186 00001269 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3187                              <1> 	;
  3188                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3189                              <1> K50:					; ALMOST-NUM-STATE
  3190 0000126B F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3191 0000126E 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3192 00001270 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3193                              <1> 	;
  3194                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3195                              <1> K52:					; NOT A NUMPAD KEY
  3196 00001272 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3197                              <1> 	;jne	short K53		; JUMP IF NOT
  3198                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3199 00001274 74AF                <1> 	je	short K45B		
  3200                              <1> 	;
  3201                              <1> 	;-----	MUST BE F11 OR F12 
  3202                              <1> K53:					; F1 - F10 COME HERE, TOO
  3203 00001276 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3204 00001279 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3205                              <1> 		; 20/02/2015 
  3206 0000127B BB[485C0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3207 00001280 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3208                              <1> 	;
  3209                              <1> 	;-----	TRANSLATE THE CHARACTER
  3210                              <1> K56:					; TRANSLATE-CHAR
  3211 00001282 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3212 00001284 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3213 00001285 F605[A65C0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3214 0000128C 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3215 0000128E B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3216 00001290 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3217                              <1> 	;
  3218                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3219                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3220 00001292 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3221 00001294 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3222 00001295 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3223 00001297 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3224 00001299 F605[A65C0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3225 000012A0 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3226 000012A2 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3227                              <1> 	;
  3228                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3229                              <1> K57:					; BUFFER_FILL
  3230 000012A4 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3231 000012A6 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3232                              <1> 	; 24/12/2021
  3233                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3234 000012A8 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3235                              <1> 	; 24/12/2021
  3236 000012AB 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3237                              <1> 	;je	K26			; INTERRUPT_RETURN
  3238                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3239 000012AD E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3240                              <1> K61:					; NOT-CAPS-STATE
  3241 000012B2 8B1D[B45C0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3242 000012B8 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3243 000012BA E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3244 000012BF 3B1D[B05C0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3245 000012C5 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3246 000012C7 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3247 000012CA 891D[B45C0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3248 000012D0 E949FDFFFF          <1> 	jmp	K26
  3249                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3250                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3251                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3252                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3253                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3254                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3255                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3256                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3257                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3258                              <1> 	;;jmp   K27                    
  3259                              <1> 	;
  3260                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3261                              <1> K62:
  3262 000012D5 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3263 000012D7 E620                <1> 	out	INTA00, al
  3264 000012D9 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3265 000012DD B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3266 000012DF E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3267 000012E4 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3268                              <1> 
  3269                              <1> SHIP_IT:
  3270                              <1> 	;---------------------------------------------------------------------------------
  3271                              <1> 	; SHIP_IT
  3272                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3273                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3274                              <1> 	;---------------------------------------------------------------------------------
  3275                              <1> 	;
  3276                              <1> 	;push	ax			; SAVE DATA TO SEND
  3277                              <1> 	; 24/12/2021
  3278 000012E9 50                  <1> 	push	eax
  3279                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3280 000012EA FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3281                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3282 000012EB B900000100          <1> 	mov	ecx, 10000h			
  3283                              <1> S10:
  3284 000012F0 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3285 000012F2 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3286 000012F4 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3287                              <1> 
  3288                              <1> 	;pop	ax			; GET DATA TO SEND
  3289                              <1> 	; 24/12/2021
  3290 000012F6 58                  <1> 	pop	eax
  3291 000012F7 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3292 000012F9 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3293 000012FA C3                  <1> 	retn				; RETURN TO CALLER
  3294                              <1> 
  3295                              <1> SND_DATA:
  3296                              <1> 	; ---------------------------------------------------------------------------------
  3297                              <1> 	; SND_DATA
  3298                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3299                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3300                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3301                              <1> 	; ---------------------------------------------------------------------------------
  3302                              <1> 	;
  3303                              <1> 	;push	ax			; SAVE REGISTERS
  3304                              <1> 	;push	bx
  3305                              <1> 	; 24/12/2021
  3306 000012FB 50                  <1> 	push	eax
  3307 000012FC 53                  <1> 	push	ebx
  3308 000012FD 51                  <1> 	push	ecx
  3309 000012FE 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3310 00001300 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3311                              <1> SD0:
  3312 00001302 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3313 00001303 8025[A55C0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3314                              <1> 	;
  3315                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3316 0000130A B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3317                              <1> SD5:
  3318 0000130F E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3319 00001311 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3320 00001313 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3321                              <1> 	;
  3322 00001315 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3323 00001317 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3324 00001319 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3325                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3326 0000131A B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3327                              <1> SD1:
  3328 0000131F F605[A55C0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3329 00001326 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3330 00001328 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3331                              <1> SD2:
  3332 0000132A FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3333 0000132C 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3334 0000132E 800D[A55C0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3335 00001335 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3336                              <1> SD3:
  3337 00001337 F605[A55C0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3338 0000133E 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3339                              <1> SD4:	
  3340 00001340 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3341                              <1> 	;pop	bx
  3342                              <1> 	;pop	ax
  3343                              <1> 	; 24/12/2021
  3344 00001341 5B                  <1> 	pop	ebx
  3345 00001342 58                  <1> 	pop	eax
  3346 00001343 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3347                              <1> 
  3348                              <1> SND_LED:
  3349                              <1> 	; ---------------------------------------------------------------------------------
  3350                              <1> 	; SND_LED
  3351                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3352                              <1> 	;
  3353                              <1> 	;----------------------------------------------------------------------------------
  3354                              <1> 	;
  3355 00001344 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3356 00001345 F605[A55C0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3357 0000134C 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3358                              <1> 	;
  3359 0000134E 800D[A55C0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3360 00001355 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3361 00001357 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3362 00001359 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3363                              <1> SND_LED1:
  3364 0000135B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3365 0000135C F605[A55C0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3366 00001363 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3367                              <1> 	;
  3368 00001365 800D[A55C0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3369                              <1> SL0:
  3370 0000136C B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3371 0000136E E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3372 00001373 FA                  <1> 	cli
  3373 00001374 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3374 00001379 8025[A55C0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3375 00001380 0805[A55C0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3376 00001386 F605[A55C0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3377 0000138D 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3378                              <1> 	;
  3379 0000138F E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3380 00001394 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3381 00001395 F605[A55C0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3382 0000139C 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3383                              <1> SL2:
  3384 0000139E B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3385 000013A0 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3386 000013A5 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3387                              <1> SL3:
  3388 000013A6 8025[A55C0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3389                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3390 000013AD FB                  <1> 	sti				; ENABLE INTERRUPTS
  3391 000013AE C3                  <1> 	retn				; RETURN TO CALLER
  3392                              <1> 
  3393                              <1> MAKE_LED:
  3394                              <1> 	;---------------------------------------------------------------------------------
  3395                              <1> 	; MAKE_LED
  3396                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3397                              <1> 	;	THE MODE INDICATORS.
  3398                              <1> 	;---------------------------------------------------------------------------------
  3399                              <1> 	;
  3400                              <1> 	;push 	cx			; SAVE CX
  3401 000013AF A0[A35C0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3402 000013B4 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3403                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3404                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3405 000013B6 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3406 000013B9 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3407                              <1> 	;pop	cx
  3408 000013BB C3                  <1> 	retn				; RETURN TO CALLER
  3409                              <1> 
  3410                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3411                              <1> 
  3412                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1832                                  
  1833                                  %include 'video.inc' ; 07/03/2015
  1834                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - VIDEO.INC
  1835                              <1> ; Last Modification: 14/06/2022
  1836                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1837                              <1> ;
  1838                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1839                              <1> 
  1840                              <1> ; 14/06/2022
  1841                              <1> ; 25/02/2022
  1842                              <1> ; 02/02/2022 (simplified scroll up)
  1843                              <1> ; 16/01/2016
  1844                              <1> ; 30/06/2015
  1845                              <1> ; 27/06/2015
  1846                              <1> ; 11/03/2015
  1847                              <1> ; 02/09/2014
  1848                              <1> ; 30/08/2014
  1849                              <1> ; VIDEO FUNCTIONS
  1850                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1851                              <1> 
  1852                              <1> write_tty:
  1853                              <1> 	; 02/02/2022
  1854                              <1> 	; 13/08/2015
  1855                              <1> 	; 02/09/2014
  1856                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1857                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1858                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1859                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1860                              <1> 	;
  1861                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1862                              <1> 	;	   AL = Character to be written
  1863                              <1> 	;	   EBX = Video Page (0 to 7)
  1864                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1865                              <1> 
  1866                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1867                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1868                              <1> 
  1869                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1870                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1871                              <1> ;
  1872                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1873                              <1> ;
  1874                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1875                              <1> ;										:
  1876                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1877                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1878                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1879                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1880                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1881                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1882                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1883                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1884                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1885                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1886                              <1> ;   THE 0 COLOR IS USED.							:
  1887                              <1> ;   ENTRY --									:
  1888                              <1> ;     (AH) = CURRENT CRT MODE							:
  1889                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1890                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1891                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1892                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1893                              <1> ;   EXIT -- 									:
  1894                              <1> ;     ALL REGISTERS SAVED							:
  1895                              <1> ;--------------------------------------------------------------------------------
  1896                              <1> 
  1897 000013BC FA                  <1> 	cli
  1898                              <1> 	;
  1899                              <1> 	; READ CURSOR (04/12/2013)
  1900                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1901 000013BD 08FF                <1> 	or	bh, bh
  1902                              <1> 	;jnz	beeper
  1903                              <1> 	; 02/02/2022
  1904 000013BF 7405                <1> 	jz	short u14
  1905 000013C1 E992000000          <1> 	jmp	beeper
  1906                              <1> u14:
  1907                              <1> 	; 02/02/2022
  1908                              <1> 	;; 01/09/2014
  1909                              <1> 	;cmp	byte [CRT_MODE], 3
  1910                              <1> 	;je	short m3
  1911                              <1> 	;;
  1912                              <1> 	;call	set_mode
  1913                              <1> m3:
  1914 000013C6 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1915                              <1> 	;shl	si, 1
  1916                              <1> 	; 02/02/2022
  1917 000013C8 D1E6                <1> 	shl	esi, 1
  1918 000013CA 81C6[66620000]      <1> 	add	esi, cursor_posn
  1919 000013D0 668B16              <1> 	mov	dx, [esi]
  1920                              <1> 	;
  1921                              <1> 	; dx now has the current cursor position
  1922                              <1> 	;
  1923 000013D3 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1924 000013D5 7647                <1> 	jbe	short u8
  1925                              <1> 	;
  1926                              <1> 	; write the char to the screen
  1927                              <1> u0:	
  1928                              <1> 	; ah = attribute/color
  1929                              <1> 	; al = character
  1930                              <1> 	; bl = video page number (0 to 7)
  1931                              <1> 	; bh = 0
  1932                              <1> 	;
  1933 000013D7 E8D2010000          <1> 	call	write_c_current
  1934                              <1> 	;
  1935                              <1> 	; position the cursor for next char
  1936 000013DC FEC2                <1> 	inc	dl		; next column
  1937                              <1> 	;cmp	dl, [CRT_COLS]
  1938 000013DE 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1939                              <1>         ;jne	set_cpos
  1940                              <1> 	; 02/02/2022
  1941 000013E1 7405                <1> 	je	short u13
  1942 000013E3 E9DE000000          <1> 	jmp	set_cpos
  1943                              <1> u13:
  1944 000013E8 B200                <1> 	mov	dl, 0		; column = 0
  1945                              <1> u10:				; (line feed found)
  1946 000013EA 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1947 000013ED 7228                <1> 	jb 	short u6
  1948                              <1> 	;
  1949                              <1> 	; scroll required
  1950                              <1> u1:	
  1951                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1952 000013EF E8D2000000          <1> 	call	set_cpos
  1953                              <1> 	;
  1954                              <1> 	; determine value to fill with during scroll
  1955                              <1> u2:
  1956                              <1> 	; READ_AC_CURRENT		:
  1957                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1958                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1959                              <1> 	;
  1960                              <1> 	; INPUT				
  1961                              <1> 	;	(AH) = CURRENT CRT MODE
  1962                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1963                              <1> 	;	(DS) = DATA SEGMENT
  1964                              <1> 	;	(ES) = REGEN SEGMENT
  1965                              <1> 	; OUTPUT			
  1966                              <1> 	;	(AL) = CHARACTER READ
  1967                              <1> 	;	(AH) = ATTRIBUTE READ
  1968                              <1> 	;
  1969                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1970                              <1> 	;
  1971                              <1> 	; bl = video page number
  1972                              <1> 	;
  1973 000013F4 E829010000          <1> 	call	find_position	; get regen location and port address
  1974                              <1> 	; dx = status port
  1975                              <1> 	; esi = cursor location/address
  1976                              <1> p11:
  1977 000013F9 FB                  <1> 	sti			; enable interrupts
  1978 000013FA 90                  <1> 	nop			; allow for small interupts window
  1979 000013FB FA                  <1> 	cli			; blocks interrupts for single loop
  1980 000013FC EC                  <1> 	in	al, dx		; get status from adapter
  1981 000013FD A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1982 000013FF 75F8                <1> 	jnz	short p11	; wait until it is
  1983                              <1> p12:				; now wait for either retrace high
  1984 00001401 EC                  <1> 	in	al, dx		; get status
  1985 00001402 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1986 00001404 74FB                <1> 	jz	short p12	; wait until either is active	
  1987                              <1> p13:
  1988 00001406 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1989 0000140C 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1990                              <1> 	;
  1991                              <1> 	; al = character, ah = attribute
  1992                              <1> 	;
  1993 0000140F FB                  <1> 	sti
  1994                              <1> 	; bl = video page number 	
  1995                              <1> u3:
  1996                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1997                              <1> 	;;sub	cx, cx		; upper left corner
  1998                              <1> 	;;mov	dh, 25-1 	; lower right row
  1999                              <1> 	;;;mov	dl, [CRT_COLS]
  2000                              <1> 	;mov	dl, 80		; lower right column	
  2001                              <1> 	;;dec	dl
  2002                              <1> 	;;mov	dl, 79
  2003                              <1> 
  2004                              <1> 	;;call	scroll_up	; 04/12/2013
  2005                              <1> 	;;; 11/03/2015
  2006                              <1> 	; 02/09/2014
  2007                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2008                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2009                              <1> 	; 11/03/2015
  2010                              <1> 	;sub	cx, cx
  2011                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2012                              <1> 	;
  2013                              <1> 	; 02/02/2022 (simplied scroll up)
  2014                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2015                              <1> 	;
  2016 00001410 B001                <1> 	mov	al, 1		; scroll 1 line up
  2017                              <1> 		; ah = attribute
  2018 00001412 E935010000          <1> 	jmp	scroll_up
  2019                              <1> ;u4:
  2020                              <1> 	;;int	10h		; video-call return
  2021                              <1> 				; scroll up the screen
  2022                              <1> 				; tty return
  2023                              <1> ;u5:
  2024                              <1> 	;retn			; return to the caller
  2025                              <1> 
  2026                              <1> u6:				; set-cursor-inc
  2027 00001417 FEC6                <1> 	inc	dh		; next row
  2028                              <1> 				; set cursor
  2029                              <1> ;u7:					
  2030                              <1> 	;;mov	ah, 02h
  2031                              <1> 	;;jmp	short u4 	; establish the new cursor
  2032                              <1> 	;call	set_cpos
  2033                              <1> 	;jmp 	short u5
  2034 00001419 E9A8000000          <1> 	jmp     set_cpos
  2035                              <1> 
  2036                              <1> 	; check for control characters
  2037                              <1> u8:
  2038 0000141E 7434                <1> 	je	short u9
  2039 00001420 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2040 00001422 74C6                <1> 	je	short u10
  2041 00001424 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2042 00001426 7430                <1> 	je	short u11
  2043 00001428 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2044                              <1> 	;jne	short u0
  2045 0000142A 7420                <1> 	je	short bs	; 12/12/2013
  2046                              <1> 	; 12/12/2013 (tab stop)
  2047 0000142C 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2048 0000142E 75A7                <1> 	jne	short u0
  2049 00001430 88D0                <1> 	mov	al, dl
  2050 00001432 6698                <1> 	cbw
  2051 00001434 B108                <1> 	mov	cl, 8
  2052 00001436 F6F1                <1> 	div	cl
  2053 00001438 28E1                <1> 	sub	cl, ah
  2054                              <1> ts:
  2055                              <1> 	; 02/09/2014
  2056                              <1> 	; 01/09/2014
  2057 0000143A B020                <1> 	mov	al, 20h
  2058                              <1> tsloop:
  2059                              <1> 	;push	cx
  2060                              <1> 	;push	ax
  2061                              <1> 	; 02/02/2022
  2062 0000143C 51                  <1> 	push	ecx
  2063 0000143D 50                  <1> 	push	eax
  2064 0000143E 30FF                <1> 	xor 	bh, bh
  2065                              <1> 	;mov	bl, [active_page]
  2066 00001440 E881FFFFFF          <1> 	call	m3
  2067                              <1> 	; 02/02/2022
  2068 00001445 58                  <1> 	pop	eax
  2069 00001446 59                  <1>  	pop	ecx
  2070                              <1> 	;pop	ax  ; ah = attribute/color
  2071                              <1> 	;pop	cx
  2072 00001447 FEC9                <1> 	dec	cl
  2073 00001449 75F1                <1> 	jnz	short tsloop
  2074 0000144B C3                  <1> 	retn
  2075                              <1> bs:	
  2076                              <1> 	; back space found
  2077 0000144C 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2078                              <1> 	;je	short u7 	; set_cursor
  2079 0000144E 7476                <1> 	jz	short set_cpos
  2080                              <1> 	;dec	dx     		; no -- just move it back
  2081                              <1> 	; 02/02/2022
  2082 00001450 FECA                <1> 	dec	dl
  2083                              <1> 	;jmp	short u7
  2084 00001452 EB72                <1> 	jmp	short set_cpos
  2085                              <1> 
  2086                              <1> 	; carriage return found
  2087                              <1> u9:
  2088 00001454 B200                <1> 	mov	dl, 0 		; move to first column
  2089                              <1> 	;jmp	short u7
  2090 00001456 EB6E                <1> 	jmp	short set_cpos
  2091                              <1> 
  2092                              <1> 	; line feed found
  2093                              <1> ;u10:
  2094                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2095                              <1> ;	jne	short u6 	; no, just set the cursor
  2096                              <1> ;       jmp     u1              ; yes, scroll the screen
  2097                              <1> 
  2098                              <1> beeper: 
  2099                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2100                              <1> 	; 18/01/2014
  2101                              <1> 	; 03/12/2013
  2102                              <1> 	; bell found
  2103                              <1> u11:
  2104 00001458 FB                  <1> 	sti
  2105 00001459 3A1D[76620000]      <1> 	cmp	bl, [active_page]
  2106 0000145F 7551                <1> 	jne	short u12	; Do not sound the beep 
  2107                              <1> 				; if it is not written on the active page
  2108 00001461 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2109 00001465 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2110                              <1> 	;call	beep		; sound the pod bell
  2111                              <1> 	;jmp	short u5 	; tty_return
  2112                              <1> 	;retn
  2113                              <1> 	
  2114                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2115                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2116                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2117                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2118                              <1> 
  2119                              <1> beep:
  2120                              <1> 	; 07/02/2015
  2121                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2122                              <1> 	; 18/01/2014
  2123                              <1> 	; 03/12/2013
  2124                              <1> 	;
  2125                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2126                              <1> 	;
  2127                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2128                              <1> 	;
  2129                              <1> 	; ENTRY:
  2130                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2131                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2132                              <1> 	; EXIT:			:
  2133                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2134                              <1> 
  2135 00001467 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2136 00001468 FA                  <1> 	cli			; block interrupts during update
  2137 00001469 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2138 0000146B E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2139 0000146D EB00                <1> 	jmp	$+2		; I/O delay
  2140 0000146F 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2141 00001471 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2142 00001473 EB00                <1> 	jmp	$+2		; I/O delay
  2143 00001475 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2144 00001477 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2145 00001479 E461                <1> 	in	al, PORT_B	; get current setting of port
  2146 0000147B 88C4                <1> 	mov	ah, al		; save that setting
  2147 0000147D 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2148 0000147F E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2149                              <1> 	;popf	; 18/01/2014
  2150 00001481 FB                  <1> 	sti
  2151                              <1> g7:				; 1/64 second per count (bl)
  2152 00001482 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2153 00001487 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2154 0000148C FECB                <1> 	dec	bl		; (bl) length count expired?
  2155 0000148E 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2156                              <1> 	;
  2157                              <1> 	;pushf			; save interrupt status
  2158 00001490 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2159 00001491 E461                <1> 	in	al, PORT_B	; get current port value
  2160                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2161 00001493 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2162 00001495 20C4                <1>         and	ah, al		; someone turned them off during beep
  2163 00001497 88E0                <1> 	mov	al, ah		; recover value of port
  2164                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2165 00001499 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2166 0000149B E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2167                              <1> 	;popf			; restore interrupt flag state
  2168 0000149D FB                  <1> 	sti
  2169 0000149E B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2170 000014A3 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2171                              <1> 	;pushf			; save interrupt status
  2172 000014A8 FA                  <1> 	cli			; block interrupts during update
  2173 000014A9 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2174 000014AB 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2175 000014AD 08E0                <1> 	or	al, ah		; recover value of port_b
  2176 000014AF E661                <1> 	out	PORT_B, al	; restore speaker status
  2177 000014B1 9D                  <1> 	popf			; restore interrupt flag state
  2178                              <1> u12:	
  2179 000014B2 C3                  <1> 	retn
  2180                              <1> 
  2181                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2182                              <1> 
  2183                              <1> WAITF:
  2184                              <1> waitf:
  2185                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2186                              <1> 	; 03/12/2013
  2187                              <1> 	;
  2188                              <1> ;	push	ax		; save work register (ah)	
  2189                              <1> ;waitf1:
  2190                              <1> 				; use timer 1 output bits
  2191                              <1> ;	in	al, PORT_B	; read current counter output status
  2192                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2193                              <1> ;	cmp	al, ah		; did it just change
  2194                              <1> ;	je	short waitf1	; wait for a change in output line
  2195                              <1> ;	;
  2196                              <1> ;	mov	ah, al		; save new lflag state
  2197                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2198                              <1> ;	;
  2199                              <1> ;	pop	ax		; restore (ah)
  2200                              <1> ;	retn			; return (cx)=0
  2201                              <1> 
  2202                              <1> ; 02/02/2022
  2203                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2204                              <1> ; 17/12/2014 (dsectrm2.s)
  2205                              <1> ; WAITF
  2206                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2207                              <1> ;
  2208                              <1> ;---WAITF-----------------------------------------------------------------------
  2209                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2210                              <1> ; ENTRY:
  2211                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2212                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2213                              <1> ; EXIT:
  2214                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2215                              <1> ;	(CX) = 0	
  2216                              <1> ;-------------------------------------------------------------------------------
  2217                              <1> 
  2218                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2219                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2220                              <1> 
  2221                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2222 000014B3 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2223                              <1> 	;push	ax
  2224                              <1> 	; 16/12/2014
  2225                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2226 000014B4 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2227                              <1> ;17/12/2014	
  2228                              <1> ;WAITF1:
  2229                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2230                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2231                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2232                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2233                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2234                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2235                              <1> 	;
  2236                              <1> 	; 17/12/2014
  2237                              <1> 	;
  2238                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2239                              <1> 	;
  2240                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2241                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2242                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2243                              <1> WR_STATE_0:
  2244 000014B6 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2245 000014B8 A810                <1> 	TEST	AL,010H
  2246 000014BA 74FA                <1> 	JZ	SHORT WR_STATE_0
  2247                              <1> WR_STATE_1:
  2248 000014BC E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2249 000014BE A810                <1> 	TEST	AL,010H
  2250 000014C0 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2251 000014C2 E2F2                <1>         LOOP    WR_STATE_0
  2252                              <1> 	;
  2253                              <1> 	;pop	ax
  2254 000014C4 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2255 000014C5 C3                  <1> 	RETn				; (CX) = 0
  2256                              <1> 
  2257                              <1> set_cpos:
  2258                              <1> 	; 14/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  2259                              <1> 	; 25/02/2022
  2260                              <1> 	; 23/02/2022
  2261                              <1> 	; 02/02/2022
  2262                              <1> 	; 27/06/2015
  2263                              <1> 	; 01/09/2014
  2264                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2265                              <1> 	;
  2266                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2267                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2268                              <1> 	;
  2269                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2270                              <1> 	;
  2271                              <1> 	; SET_CPOS
  2272                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2273                              <1> 	;	NEW X-Y VALUES PASSED
  2274                              <1> 	; INPUT
  2275                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2276                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2277                              <1> 	; OUTPUT
  2278                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2279                              <1> 	;
  2280 000014C6 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2281 000014C9 D0E0                <1>         shl     al, 1   ; word offset
  2282 000014CB BE[66620000]        <1> 	mov	esi, cursor_posn
  2283 000014D0 01C6                <1>         add     esi, eax
  2284 000014D2 668916              <1> 	mov	[esi], dx ; save the pointer
  2285 000014D5 381D[76620000]      <1> 	cmp	[active_page], bl
  2286 000014DB 7531                <1> 	jne	short m17
  2287                              <1> 
  2288                              <1> 	; 14/06/2022	
  2289                              <1> 	;cli ; 25/02/2022
  2290                              <1> 
  2291                              <1> 	;call	m18	;h CURSOR SET
  2292                              <1> ;m17:			; SET_CPOS_RETURN
  2293                              <1> 	; 01/09/2014
  2294                              <1> 	;retn
  2295                              <1> 		; DX = row/column
  2296                              <1> m18:
  2297 000014DD E832000000          <1> 	call	position ; determine location in regen buffer	
  2298                              <1> 	;mov	cx, [CRT_START]
  2299                              <1> 	; 23/02/2022
  2300 000014E2 0FB70D[64620000]    <1> 	movzx	ecx, word [CRT_START]
  2301 000014E9 01C1                <1> 	add	ecx, eax
  2302                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2303                              <1> 			; to the start address (offset) for this page
  2304                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2305                              <1> 	; 23/02/2022
  2306 000014EB D1E9                <1> 	shr	ecx, 1
  2307 000014ED B40E                <1> 	mov	ah, 14	; register number for cursor
  2308                              <1> 	
  2309                              <1> 	; 14/06/2022
  2310                              <1> 	;call	m16	; output value to the 6845
  2311                              <1> 	;sti	; 25/02/2022
  2312                              <1> 	;retn
  2313                              <1> 
  2314                              <1> 	; 14/06/2022
  2315                              <1> 	; 25/02/2022
  2316                              <1> 	; 02/02/2022
  2317                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2318                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2319                              <1> m16:
  2320                              <1> 	; 14/06/2022
  2321 000014EF FA                  <1> 	cli	; 25/02/2022
  2322                              <1> 	;mov	dx, [addr_6845] ; address register
  2323 000014F0 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2324 000014F4 88E0                <1> 	mov	al, ah	; get value
  2325 000014F6 EE                  <1> 	out	dx, al	; register set
  2326                              <1> 	;inc	dx	; data register
  2327                              <1> 	; 02/02/2022
  2328 000014F7 FEC2                <1> 	inc	dl
  2329 000014F9 EB00                <1> 	jmp	$+2	; i/o delay
  2330 000014FB 88E8                <1> 	mov	al, ch	; data
  2331 000014FD EE                  <1> 	out	dx, al	
  2332                              <1> 	;dec	dx
  2333                              <1> 	; 02/02/2022	
  2334 000014FE FECA                <1> 	dec	dl
  2335 00001500 88E0                <1> 	mov	al, ah
  2336 00001502 FEC0                <1> 	inc	al	; point to other data register
  2337 00001504 EE                  <1> 	out	dx, al	; set for second register
  2338                              <1> 	;inc	dx
  2339                              <1> 	; 02/02/2022
  2340 00001505 FEC2                <1> 	inc	dl
  2341 00001507 EB00                <1> 	jmp	$+2	; i/o delay
  2342 00001509 88C8                <1> 	mov	al, cl	; second data value
  2343 0000150B EE                  <1> 	out	dx, al
  2344                              <1> 	; 14/06/2022
  2345 0000150C FB                  <1> 	sti	; 25/02/2022
  2346                              <1> ;m17:
  2347 0000150D C3                  <1> 	retn
  2348                              <1> m17:
  2349                              <1> 	; 14/06/2022
  2350                              <1> 	; ('write_tty' must not return to 'putc' with cf)
  2351 0000150E F8                  <1> 	clc
  2352 0000150F C3                  <1> 	retn
  2353                              <1> 
  2354                              <1> set_ctype:
  2355                              <1> 	; 07/02/2022
  2356                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2357                              <1> 	;
  2358                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2359                              <1> 
  2360                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2361                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2362                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2363                              <1> ;          OR NO CURSOR AT ALL
  2364                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2365                              <1> 
  2366                              <1> ;------------------------------------------------
  2367                              <1> ; SET_CTYPE
  2368                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2369                              <1> ; INPUT
  2370                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2371                              <1> ; OUTPUT	
  2372                              <1> ;	NONE
  2373                              <1> ;------------------------------------------------
  2374                              <1> 
  2375 00001510 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2376                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2377                              <1> 	;call	m16	; output cx register
  2378                              <1> 	;retn
  2379                              <1> 	; 07/02/2022
  2380 00001512 EBDB                <1> 	jmp	short m16
  2381                              <1> 
  2382                              <1> position:
  2383                              <1> 	; 23/02/2022
  2384                              <1> 	; 02/02/2022
  2385                              <1> 	; 27/06/2015
  2386                              <1> 	; 02/09/2014
  2387                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2388                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2389                              <1> 	;
  2390                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2391                              <1> 	;
  2392                              <1> 	; POSITION
  2393                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2394                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2395                              <1> 	; INPUT
  2396                              <1> 	;	AX = ROW, COLUMN POSITION
  2397                              <1> 	; OUTPUT
  2398                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2399                              <1> 
  2400                              <1> 		; DX = ROW, COLUMN POSITION
  2401                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2402 00001514 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2403 00001516 B050                <1> 	mov	al, 80	; determine bytes to row	
  2404 00001518 F6E6                <1> 	mul	dh	; row value
  2405                              <1> 	;xor	dh, dh	; 0
  2406                              <1> 	;add	ax, dx	; add column value to the result
  2407                              <1> 	; 23/02/2022
  2408 0000151A 00D0                <1> 	add	al, dl
  2409 0000151C 80D400              <1> 	adc	ah, 0	
  2410                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2411                              <1> 	; 02/02/2022
  2412 0000151F D1E0                <1> 	shl	eax, 1
  2413                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2414 00001521 C3                  <1> 	retn
  2415                              <1> 
  2416                              <1> find_position:
  2417                              <1> 	; 02/02/2022
  2418                              <1> 	; 27/06/2015
  2419                              <1> 	; 07/09/2014
  2420                              <1> 	; 02/09/2014
  2421                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2422                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2423 00001522 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2424 00001525 89CE                <1> 	mov	esi, ecx
  2425                              <1> 	;shl	si, 1
  2426                              <1> 	; 02/02/2022
  2427 00001527 D1E6                <1> 	shl	esi, 1
  2428 00001529 668B96[66620000]    <1> 	mov	dx, [esi+cursor_posn]
  2429 00001530 7409                <1> 	jz	short p21
  2430                              <1> 	;xor	si, si
  2431                              <1> 	; 02/02/2022
  2432 00001532 31F6                <1> 	xor	esi, esi
  2433                              <1> p20:
  2434                              <1> 	;add	si, [CRT_LEN]
  2435 00001534 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2436 00001539 E2F9                <1> 	loop	p20
  2437                              <1> p21:
  2438 0000153B 6621D2              <1> 	and	dx, dx
  2439 0000153E 7407                <1> 	jz	short p22
  2440 00001540 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2441 00001545 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2442                              <1> p22:	
  2443                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2444                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2445                              <1> 	;add	dx, 6	; point at status port
  2446 00001547 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2447                              <1> 	; cx = 0
  2448 0000154B C3                  <1> 	retn
  2449                              <1> 
  2450                              <1> scroll_up:
  2451                              <1> 	; 02/02/2022 (simplified scroll up)
  2452                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2453                              <1> 	; 16/01/2016
  2454                              <1> 	; 07/09/2014
  2455                              <1> 	; 02/09/2014
  2456                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2457                              <1> 	; 04/04/2014
  2458                              <1> 	; 04/12/2013
  2459                              <1> 	;
  2460                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2461                              <1> 	;
  2462                              <1> 	; SCROLL UP
  2463                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2464                              <1> 	;	ON THE SCREEN
  2465                              <1> 	; INPUT
  2466                              <1> 	;	(AH) = CURRENT CRT MODE
  2467                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2468                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2469                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2470                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2471                              <1> 	;	(DS) = DATA SEGMENT
  2472                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2473                              <1> 	; OUTPUT
  2474                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2475                              <1> 	;
  2476                              <1> 	;	bh = 0  (02/09/2014)
  2477                              <1> 	;
  2478                              <1> 	; ((ah = 3))
  2479                              <1> 	; cl = left upper column
  2480                              <1> 	; ch = left upper row
  2481                              <1> 	; dl = right lower column
  2482                              <1> 	; dh = right lower row
  2483                              <1> 	;
  2484                              <1> 	; al = line count 
  2485                              <1> 	; ah = attribute to be used on blanked line
  2486                              <1> 	; bl = video page number (0 to 7)
  2487                              <1> 	; 
  2488                              <1> 
  2489                              <1> 	; 02/02/2022 'scroll_up' code
  2490                              <1> 	; ------------------------------------------------------
  2491                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2492                              <1> 
  2493                              <1> 	; INPUT:
  2494                              <1> 	;		
  2495                              <1> 	; al = line count 
  2496                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2497                              <1> 	; ah = attribute to be used on blanked line
  2498                              <1> 	; bl = video page number (0 to 7)
  2499                              <1> 
  2500                              <1> 	;cli
  2501 0000154C 31C9                <1> 	xor	ecx, ecx
  2502 0000154E 88C1                <1> 	mov	cl, al ; line count (cl)
  2503 00001550 BE00800B00          <1> 	mov	esi, 0B8000h
  2504 00001555 3A1D[76620000]      <1> 	cmp	bl, [active_page]
  2505 0000155B 7411                <1> 	je	short n1
  2506 0000155D 20DB                <1> 	and	bl, bl
  2507 0000155F 7422                <1> 	jz	short n3
  2508 00001561 88DD                <1> 	mov	ch, bl ; video page number
  2509                              <1> n0:
  2510 00001563 6681C6A00F          <1> 	add	si, 25*80*2
  2511 00001568 FECD                <1> 	dec	ch
  2512 0000156A 75F7                <1> 	jnz	short n0
  2513 0000156C EB15                <1> 	jmp	short n3
  2514                              <1> n1:
  2515 0000156E 660335[64620000]    <1> 	add	si, [CRT_START]
  2516                              <1> 	;
  2517 00001575 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2518                              <1> n2:			 ; wait_display_enable
  2519 00001579 EC                  <1> 	in	al, dx	 ; get port
  2520 0000157A A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2521 0000157C 74FB                <1> 	jz	short n2 ; wait_display_enable
  2522 0000157E B025                <1> 	mov	al, 25h
  2523 00001580 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2524 00001582 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2525                              <1> n3:
  2526                              <1> 	; cl = line count
  2527                              <1> 	; ah = attribute/color
  2528 00001583 89F7                <1> 	mov	edi, esi
  2529 00001585 20C9                <1> 	and	cl, cl
  2530 00001587 741F                <1> 	jz	short n6
  2531 00001589 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2532 0000158E 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2533 00001592 F366A5              <1> 	rep	movsw
  2534 00001595 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2535                              <1> n4:
  2536                              <1> 	; ah = character attribute/cocor
  2537 00001597 B020                <1> 	mov	al, 20h ; fill with blanks
  2538 00001599 F366AB              <1> 	rep	stosw
  2539                              <1> 
  2540 0000159C 3A1D[76620000]      <1> 	cmp	bl, [active_page]
  2541 000015A2 7503                <1> 	jne	short n5
  2542                              <1> 
  2543                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2544 000015A4 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2545                              <1> 	;mov	dx, 03D8h ; always set color card port
  2546 000015A6 EE                  <1> 	out	dx, al
  2547                              <1> n5:
  2548 000015A7 C3                  <1> 	retn
  2549                              <1> n6:
  2550                              <1> 	; clear video page
  2551 000015A8 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2552 000015AC EBE9                <1> 	jmp	short n4
  2553                              <1> 
  2554                              <1> 	; 23/02/2022
  2555                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2556                              <1> 	; ------------------------------------------------------
  2557                              <1> 
  2558                              <1> 	; Test	Line Count
  2559                              <1> 	or	al, al
  2560                              <1> 	jz	short al_set
  2561                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2562                              <1> 	sub	bh, ch
  2563                              <1> 	inc	bh	; adjust difference by 1
  2564                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2565                              <1> 	jne	short al_set ; if not the we're all set
  2566                              <1> 	xor	al, al	; otherwise set al to zero
  2567                              <1> al_set:
  2568                              <1> 	xor	bh, bh	; 0
  2569                              <1> 	;push	ax
  2570                              <1> 	push	eax ; 23/02/2022
  2571                              <1> 	;mov 	esi, [crt_base]
  2572                              <1>         mov     esi, 0B8000h  
  2573                              <1>         cmp     bl, [active_page]
  2574                              <1> 	jne	short n0
  2575                              <1> 	;
  2576                              <1>         mov     ax, [CRT_START]
  2577                              <1>         add     si, ax
  2578                              <1>         jmp     short n1
  2579                              <1> n0:
  2580                              <1>         and     bl, bl
  2581                              <1> 	jz	short n1
  2582                              <1> 	mov	al, bl
  2583                              <1> n0x:
  2584                              <1>         ;add    si, [CRT_LEN]
  2585                              <1>         ;add    esi, 80*25*2 
  2586                              <1>         add     si, 80*25*2
  2587                              <1>         dec	al
  2588                              <1> 	jnz	short n0x
  2589                              <1> n1:	
  2590                              <1>         ; Scroll position
  2591                              <1> 	;push	dx ; 23/02/2022
  2592                              <1> 	mov	dx, cx	; now, upper left position in DX
  2593                              <1> 	call	position
  2594                              <1> 	add	esi, eax
  2595                              <1> 	mov	edi, esi
  2596                              <1> 	;pop	dx	; lower right position in DX
  2597                              <1> 	sub	dx, cx
  2598                              <1> 	inc	dh	; dh = #rows 
  2599                              <1> 	inc	dl	; dl = #cols in block
  2600                              <1> 	;pop	ax	; al = line count, ah = attribute
  2601                              <1> 	pop	eax ; 23/02/2022
  2602                              <1> 	xor	ecx, ecx
  2603                              <1> 	mov	cx, ax
  2604                              <1> 	;mov	ah, [CRT_COLS]
  2605                              <1> 	mov	ah, 80
  2606                              <1> 	mul	ah	; determine offset to from address
  2607                              <1> 	add	ax, ax  ; *2 for attribute byte
  2608                              <1> 	;
  2609                              <1> 	;push	ax	; offset 
  2610                              <1> 	;push	dx
  2611                              <1> 	; 23/02/2022
  2612                              <1> 	push	eax
  2613                              <1> 	push	edx
  2614                              <1> 	;
  2615                              <1> 	; 04/04/2014
  2616                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2617                              <1> n8:                      ; wait_display_enable
  2618                              <1>         in      al, dx   ; get port
  2619                              <1> 	test	al, RVRT ; wait for vertical retrace
  2620                              <1> 	jz	short n8 ; wait_display_enable
  2621                              <1> 	mov	al, 25h
  2622                              <1> 	mov	dl, 0D8h ; address control port
  2623                              <1> 	out	dx, al	; turn off video during vertical retrace
  2624                              <1> 	;pop	dx	; #rows, #cols
  2625                              <1>        	;pop	ax	; offset
  2626                              <1> 	; 23/02/2022
  2627                              <1> 	pop	edx
  2628                              <1> 	pop	eax
  2629                              <1> 	xchg	ax, cx	; 
  2630                              <1> 	; ecx = offset, al = line count, ah = attribute
  2631                              <1> ;n9:
  2632                              <1> 	or	al, al
  2633                              <1>         jz      short n3 
  2634                              <1>         add     esi, ecx ; from address for scroll
  2635                              <1> 	mov	bh, dh  ; #rows in block
  2636                              <1> 	sub	bh, al	; #rows to be moved
  2637                              <1> n2:
  2638                              <1> 	; Move rows
  2639                              <1> 	mov	cl, dl	; get # of cols to move
  2640                              <1> 	push	esi
  2641                              <1> 	push	edi	; save start address
  2642                              <1> n10:
  2643                              <1> 	movsw		; move that line on screen
  2644                              <1> 	dec	cl
  2645                              <1>         jnz     short n10
  2646                              <1> 	pop	edi
  2647                              <1> 	pop	esi	; recover addresses
  2648                              <1>         ;mov    cl, [CRT_COLS] 
  2649                              <1> 	;add	cl, cl
  2650                              <1>         ;mov    ecx, 80*2
  2651                              <1>         mov     cx, 80*2
  2652                              <1>         add     esi, ecx  ; next line
  2653                              <1>         add     edi, ecx
  2654                              <1> 	dec	bh	 ; count of lines to move
  2655                              <1> 	jnz	short n2 ; row loop
  2656                              <1> 	; bh = 0
  2657                              <1> 	mov	dh, al	 ; #rows	
  2658                              <1> n3:
  2659                              <1> 	; attribute in ah
  2660                              <1> 	mov	al, ' '	 ; fill with blanks
  2661                              <1> n3x:
  2662                              <1> 	; Clear rows
  2663                              <1>                 ; dh =  #rows
  2664                              <1>         mov	cl, dl	; get # of cols to clear
  2665                              <1>         push    edi     ; save address
  2666                              <1> n11:
  2667                              <1>         stosw           ; store fill character
  2668                              <1> 	dec	cl
  2669                              <1>         jnz     short n11
  2670                              <1>         pop     edi     ; recover address
  2671                              <1> 	;mov	cl, [CRT_COLS]
  2672                              <1> 	;add	cl, cl
  2673                              <1>         ;mov    ecx, 80*2
  2674                              <1>         mov	cl, 80*2
  2675                              <1>         add     edi, ecx
  2676                              <1> 	dec	dh
  2677                              <1> 	jnz	short n3x ; 16/01/2016
  2678                              <1> 	;
  2679                              <1> 	cmp	bl, [active_page]
  2680                              <1> 	jne	short n6
  2681                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2682                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2683                              <1> 	mov	dx, 03D8h ; always set color card port
  2684                              <1> 	out	dx, al
  2685                              <1> n6:
  2686                              <1> 	retn
  2687                              <1> 
  2688                              <1> %endif
  2689                              <1> 
  2690                              <1> write_c_current:
  2691                              <1> 	; 02/02/2022
  2692                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2693                              <1> 	; 18/01/2014
  2694                              <1> 	; 04/12/2013
  2695                              <1> 	;
  2696                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2697                              <1> 	;
  2698                              <1> 	; WRITE_C_CURRENT
  2699                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2700                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2701                              <1> 	; INPUT	
  2702                              <1> 	;	(AH) = CURRENT CRT MODE
  2703                              <1> 	;	(BH) = DISPLAY PAGE
  2704                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2705                              <1> 	;	(AL) = CHAR TO WRITE
  2706                              <1> 	;	(DS) = DATA SEGMENT
  2707                              <1> 	;	(ES) = REGEN SEGMENT
  2708                              <1> 	; OUTPUT
  2709                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2710                              <1> 
  2711 000015AE FA                  <1> 	cli		
  2712                              <1> 	; bl = video page
  2713                              <1> 	; al = character
  2714                              <1> 	; ah = color/attribute
  2715                              <1> 	;push	dx
  2716                              <1> 	;push	ax	; save character & attribute/color
  2717                              <1> 	; 02/02/2022
  2718 000015AF 52                  <1> 	push	edx
  2719 000015B0 50                  <1> 	push	eax
  2720 000015B1 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2721                              <1> 	; esi = regen location
  2722                              <1> 	; dx = status port
  2723                              <1> 	;
  2724                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2725                              <1> 	;
  2726                              <1> p41:			; wait for horizontal retrace is low or vertical
  2727 000015B6 FB                  <1> 	sti		; enable interrupts first
  2728 000015B7 3A1D[76620000]      <1>         cmp     bl, [active_page]
  2729 000015BD 7510                <1> 	jne	short p44 
  2730 000015BF FA                  <1> 	cli 		; block interrupts for single loop
  2731 000015C0 EC                  <1> 	in	al, dx	; get status from the adapter
  2732 000015C1 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2733 000015C3 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2734 000015C5 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2735 000015C7 75ED                <1> 	jnz	short p41 ; wait until it is
  2736                              <1> p42:			; wait for either retrace high
  2737 000015C9 EC                  <1> 	in	al, dx	; get status again
  2738 000015CA A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2739 000015CC 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2740                              <1> p43:	
  2741 000015CE FB                  <1> 	sti
  2742                              <1> p44:
  2743                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2744                              <1> 	; 02/02/2022
  2745 000015CF 58                  <1> 	pop	eax
  2746 000015D0 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2747                              <1> 			; Retro UNIX 386 v1 feature only!
  2748 000015D6 668906              <1> 	mov	[esi], ax
  2749                              <1> 	;pop	dx
  2750                              <1> 	; 02/02/2022
  2751 000015D9 5A                  <1> 	pop	edx
  2752 000015DA C3                  <1> 	retn
  2753                              <1> 
  2754                              <1> %if 0	; 02/02/2022
  2755                              <1> 
  2756                              <1> set_mode:
  2757                              <1> 	; 02/02/2022
  2758                              <1> 	; 16/01/2016
  2759                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2760                              <1> 	;
  2761                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2762                              <1> 
  2763                              <1> ;------------------------------------------------------
  2764                              <1> ; SET MODE					      :
  2765                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2766                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2767                              <1> ; INPUT						      :
  2768                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2769                              <1> ; OUTPUT					      :
  2770                              <1> ;	NONE					      :
  2771                              <1> ;------------------------------------------------------
  2772                              <1> 
  2773                              <1> 	push	edi ; 16/01/2016
  2774                              <1> 	push	ebx
  2775                              <1> 	push	edx
  2776                              <1> 	push	ecx ; 16/01/2016
  2777                              <1>         push    eax
  2778                              <1> 
  2779                              <1> 	;mov	dx, 03D4h 	; address or color card
  2780                              <1> 	mov	al, 3
  2781                              <1> ;M8:
  2782                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2783                              <1> 	mov	al, 29h
  2784                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2785                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2786                              <1> 	;push	dx  		; save port value
  2787                              <1> 	;add	dx, 4		; point to control register
  2788                              <1> 	mov	dx, 3D8h
  2789                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2790                              <1> 	;pop	dx
  2791                              <1> ;M9:
  2792                              <1> 	mov	ebx, video_params ; initialization table
  2793                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2794                              <1> 	;xchg 	ah, al
  2795                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2796                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2797                              <1> 	
  2798                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2799                              <1> 	; 02/02/2022
  2800                              <1> 	; dx = 3D8h
  2801                              <1> 	xor	ecx, ecx
  2802                              <1> 	mov	cl, 16
  2803                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2804                              <1> M10:			;  initialization loop
  2805                              <1> 	mov	al, ah 	; get 6845 register number
  2806                              <1> 	out	dx, al
  2807                              <1> 	;inc	dx      ; point to data port
  2808                              <1> 	; 02/02/2022
  2809                              <1> 	inc	dl ; 3D9h
  2810                              <1> 	inc	ah	; next register value
  2811                              <1> 	mov	al, [ebx] ; get table value
  2812                              <1> 	out	dx, al	; out to chip
  2813                              <1> 	inc	ebx	; next in table
  2814                              <1> 	;dec	dx	; back to pointer register
  2815                              <1> 	; 02/02/2022
  2816                              <1> 	dec	dl ; 3D8h
  2817                              <1> 	loop	M10	; do the whole table
  2818                              <1> 	
  2819                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2820                              <1> 	;xor	ax, ax  
  2821                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2822                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2823                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2824                              <1> 	; black background, light gray characeter color, space character
  2825                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2826                              <1> ;M13:			  ; clear buffer
  2827                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2828                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2829                              <1> 
  2830                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2831                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2832                              <1> 			 ; prepare to output to video enable port
  2833                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2834                              <1> 	; 02/02/2022
  2835                              <1> 	;mov	dx, 3D8h
  2836                              <1> 	; 
  2837                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2838                              <1> 	mov	al, 29h
  2839                              <1> 	out	dx, al	 ; set video enable port
  2840                              <1> 
  2841                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2842                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2843                              <1> 	;
  2844                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2845                              <1> 	;
  2846                              <1> ;-----	SET CURSOR POSITIONS
  2847                              <1> 	;push	edi
  2848                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2849                              <1> 	mov	edi, cursor_posn
  2850                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2851                              <1> 	xor	eax, eax
  2852                              <1> 	rep 	stosd	; fill with zeroes
  2853                              <1> 	;pop	edi
  2854                              <1> 
  2855                              <1> ;-----	SET UP OVERSCAN REGISTER
  2856                              <1> 	inc	dx	; set overscan port to a default
  2857                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2858                              <1> ;M14:
  2859                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2860                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2861                              <1> 
  2862                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2863                              <1> 	;
  2864                              <1> 	pop	eax
  2865                              <1> 	pop	ecx ; 16/01/2016
  2866                              <1> 	pop	edx
  2867                              <1> 	pop	ebx
  2868                              <1> 	pop	edi ; 16/01/2016
  2869                              <1> 	retn
  2870                              <1> 
  2871                              <1> %endif
  2872                              <1> 	
  2873                              <1> tty_sw:
  2874                              <1> 	; 02/02/2022
  2875                              <1> 	; 30/06/2015
  2876                              <1> 	; 27/06/2015 
  2877                              <1> 	; 07/09/2014
  2878                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2879                              <1> 	;
  2880                              <1> 	; (Modified registers : EAX)
  2881                              <1> 	;
  2882                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2883                              <1> 	;
  2884                              <1> ;act_disp_page:
  2885                              <1> 	; 30/06/2015
  2886                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2887                              <1> 	; 10/12/2013
  2888                              <1> 	; 04/12/2013
  2889                              <1> 	;
  2890                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2891                              <1> 	;
  2892                              <1> 	; ACT_DISP_PAGE
  2893                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2894                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2895                              <1> 	; INPUT
  2896                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2897                              <1> 	; OUTPUT
  2898                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2899                              <1> 
  2900                              <1> 	;cli
  2901                              <1> 
  2902 000015DB 53                  <1> 	push	ebx
  2903                              <1> 	;push	cx
  2904                              <1> 	;push	dx
  2905                              <1> 	; 02/02/2022
  2906 000015DC 51                  <1> 	push	ecx
  2907 000015DD 52                  <1> 	push	edx
  2908                              <1> 	;
  2909 000015DE A2[76620000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2910                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2911                              <1> 	;mov	cx, 25*80*2
  2912                              <1> 	; 02/02/2022
  2913 000015E3 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2914                              <1> 	; 27/06/2015
  2915 000015E8 0FB6D8              <1> 	movzx	ebx, al
  2916                              <1> 	; 02/02/2022
  2917 000015EB 89D8                <1> 	mov	eax, ebx
  2918                              <1> 	;
  2919                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2920                              <1> 	;mul 	cx	; display page times regen length
  2921                              <1> 	; 02/02/2022
  2922 000015ED F7E1                <1> 	mul	ecx	
  2923                              <1> 	; 10/12/2013
  2924 000015EF 66A3[64620000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2925                              <1> 	;mov	cx, ax	; start address to cx
  2926                              <1> 	; 02/02/2022
  2927 000015F5 89C1                <1> 	mov	ecx, eax
  2928                              <1> 	;sar	cx, 1
  2929                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2930                              <1> 	; 02/02/2022
  2931 000015F7 D1E9                <1> 	shr	ecx, 1
  2932 000015F9 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2933 000015FB E8EFFEFFFF          <1> 	call	m16
  2934                              <1> 	;sal	bx, 1
  2935                              <1> 	; 01/09/2014
  2936 00001600 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2937 00001602 81C3[66620000]      <1> 	add	ebx, cursor_posn
  2938 00001608 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2939 0000160B E8CDFEFFFF          <1> 	call	m18
  2940                              <1> 	;
  2941                              <1> 	;pop	dx
  2942                              <1> 	;pop	cx
  2943                              <1> 	; 02/02/2022
  2944 00001610 5A                  <1> 	pop	edx
  2945 00001611 59                  <1> 	pop	ecx
  2946 00001612 5B                  <1> 	pop	ebx
  2947                              <1> 	;
  2948                              <1> 	;sti
  2949                              <1> 	;
  2950 00001613 C3                  <1> 	retn
  2951                              <1> 
  2952                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2953                              <1> 
  2954                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1834                                  
  1835                                  setup_rtc_int:
  1836                                  ; source: http://wiki.osdev.org/RTC
  1837 00001614 FA                      	cli		; disable interrupts
  1838                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1839                                  	; in order to change this ...
  1840                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1841                                  	; (rate must be above 2 and not over 15)
  1842                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1843 00001615 B08A                    	mov	al, 8Ah 
  1844 00001617 E670                    	out	70h, al ; set index to register A, disable NMI
  1845 00001619 90                      	nop
  1846 0000161A E471                    	in	al, 71h ; get initial value of register A
  1847 0000161C 88C4                    	mov 	ah, al
  1848 0000161E 80E4F0                  	and	ah, 0F0h
  1849 00001621 B08A                    	mov	al, 8Ah 
  1850 00001623 E670                    	out	70h, al ; reset index to register A
  1851 00001625 88E0                    	mov	al, ah
  1852 00001627 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1853 00001629 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1854                                  	; enable RTC interrupt
  1855 0000162B B08B                    	mov	al, 8Bh ;
  1856 0000162D E670                    	out	70h, al ; select register B and disable NMI
  1857 0000162F 90                      	nop
  1858 00001630 E471                    	in	al, 71h ; read the current value of register B
  1859 00001632 88C4                    	mov	ah, al  ;
  1860 00001634 B08B                    	mov 	al, 8Bh ;
  1861 00001636 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1862 00001638 88E0                    	mov	al, ah  ;
  1863 0000163A 0C40                    	or	al, 40h ;
  1864 0000163C E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1865 0000163E FB                      	sti
  1866 0000163F C3                      	retn
  1867                                  
  1868                                  ; Write memory information
  1869                                  ; Temporary Code
  1870                                  ; 06/11/2014
  1871                                  ; 14/08/2015 
  1872                                  memory_info:	
  1873 00001640 A1[4C620000]            	mov	eax, [memory_size] ; in pages
  1874 00001645 50                      	push	eax
  1875 00001646 C1E00C                  	shl	eax, 12		   ; in bytes
  1876 00001649 BB0A000000              	mov	ebx, 10
  1877 0000164E 89D9                    	mov	ecx, ebx	   ; 10
  1878 00001650 BE[B35E0000]            	mov	esi, mem_total_b_str	
  1879 00001655 E8B2000000              	call	bintdstr
  1880 0000165A 58                      	pop	eax
  1881 0000165B B107                    	mov	cl, 7
  1882 0000165D BE[D75E0000]            	mov	esi, mem_total_p_str
  1883 00001662 E8A5000000              	call	bintdstr	
  1884                                  	; 14/08/2015
  1885 00001667 E8BD000000              	call	calc_free_mem
  1886                                  	; edx = calculated free pages
  1887                                  	; ecx = 0
  1888 0000166C A1[50620000]            	mov 	eax, [free_pages]
  1889 00001671 39D0                    	cmp	eax, edx ; calculated free mem value 
  1890                                  		; and initial free mem value are same or not?
  1891 00001673 751D                    	jne 	short pmim ; print mem info with '?' if not
  1892 00001675 52                      	push 	edx ; free memory in pages	
  1893                                  	;mov 	eax, edx
  1894 00001676 C1E00C                  	shl	eax, 12 ; convert page count
  1895                                  			; to byte count
  1896 00001679 B10A                    	mov	cl, 10
  1897 0000167B BE[F75E0000]            	mov	esi, free_mem_b_str
  1898 00001680 E887000000              	call	bintdstr
  1899 00001685 58                      	pop	eax
  1900 00001686 B107                    	mov	cl, 7
  1901 00001688 BE[1B5F0000]            	mov	esi, free_mem_p_str
  1902 0000168D E87A000000              	call	bintdstr
  1903                                  pmim:
  1904 00001692 BE[A15E0000]            	mov	esi, msg_memory_info
  1905                                  pmim_nb:	
  1906 00001697 AC                      	lodsb
  1907 00001698 08C0                    	or	al, al
  1908 0000169A 740D                    	jz	short pmim_ok
  1909 0000169C 56                      	push	esi
  1910 0000169D 31DB                    	xor	ebx, ebx ; 0
  1911                                  			; Video page 0 (bl=0)
  1912 0000169F B407                    	mov	ah, 07h ; Black background, 
  1913                                  			; light gray forecolor
  1914 000016A1 E816FDFFFF              	call	write_tty
  1915 000016A6 5E                      	pop	esi
  1916 000016A7 EBEE                    	jmp	short pmim_nb
  1917                                  pmim_ok:
  1918 000016A9 C3                      	retn
  1919                                  
  1920                                  ; Convert binary number to hexadecimal string
  1921                                  ; 10/05/2015  
  1922                                  ; dsectpm.s (28/02/2015)
  1923                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1924                                  ; 01/12/2014
  1925                                  ; 25/11/2014
  1926                                  ;
  1927                                  bytetohex:
  1928                                  	; INPUT ->
  1929                                  	; 	AL = byte (binary number)
  1930                                  	; OUTPUT ->
  1931                                  	;	AX = hexadecimal string
  1932                                  	;
  1933 000016AA 53                      	push	ebx
  1934 000016AB 31DB                    	xor	ebx, ebx
  1935 000016AD 88C3                    	mov	bl, al
  1936 000016AF C0EB04                  	shr	bl, 4
  1937 000016B2 8A9B[FC160000]          	mov	bl, [ebx+hexchrs] 	 	
  1938 000016B8 86D8                    	xchg	bl, al
  1939 000016BA 80E30F                  	and	bl, 0Fh
  1940 000016BD 8AA3[FC160000]          	mov	ah, [ebx+hexchrs] 
  1941 000016C3 5B                      	pop	ebx	
  1942 000016C4 C3                      	retn
  1943                                  
  1944                                  wordtohex:
  1945                                  	; INPUT ->
  1946                                  	; 	AX = word (binary number)
  1947                                  	; OUTPUT ->
  1948                                  	;	EAX = hexadecimal string
  1949                                  	;
  1950 000016C5 53                      	push	ebx
  1951 000016C6 31DB                    	xor	ebx, ebx
  1952 000016C8 86E0                    	xchg	ah, al
  1953 000016CA 6650                    	push	ax
  1954 000016CC 88E3                    	mov	bl, ah
  1955 000016CE C0EB04                  	shr	bl, 4
  1956 000016D1 8A83[FC160000]          	mov	al, [ebx+hexchrs] 	 	
  1957 000016D7 88E3                    	mov	bl, ah
  1958 000016D9 80E30F                  	and	bl, 0Fh
  1959 000016DC 8AA3[FC160000]          	mov	ah, [ebx+hexchrs]
  1960 000016E2 C1E010                  	shl	eax, 16
  1961 000016E5 6658                    	pop	ax
  1962 000016E7 5B                      	pop	ebx
  1963 000016E8 EBC0                    	jmp	short bytetohex
  1964                                  	;mov	bl, al
  1965                                  	;shr	bl, 4
  1966                                  	;mov	bl, [ebx+hexchrs] 	 	
  1967                                  	;xchg	bl, al	 	
  1968                                  	;and	bl, 0Fh
  1969                                  	;mov	ah, [ebx+hexchrs] 
  1970                                  	;pop	ebx	
  1971                                  	;retn
  1972                                  
  1973                                  dwordtohex:
  1974                                  	; INPUT ->
  1975                                  	; 	EAX = dword (binary number)
  1976                                  	; OUTPUT ->
  1977                                  	;	EDX:EAX = hexadecimal string
  1978                                  	;
  1979 000016EA 50                      	push	eax
  1980 000016EB C1E810                  	shr	eax, 16
  1981 000016EE E8D2FFFFFF              	call	wordtohex
  1982 000016F3 89C2                    	mov	edx, eax
  1983 000016F5 58                      	pop	eax
  1984 000016F6 E8CAFFFFFF              	call	wordtohex
  1985 000016FB C3                      	retn
  1986                                  
  1987                                  ; 10/05/2015
  1988                                  hex_digits:
  1989                                  hexchrs:
  1990 000016FC 303132333435363738-     	db '0123456789ABCDEF'
  1990 00001705 39414243444546     
  1991                                  
  1992                                  ; Convert binary number to decimal/numeric string
  1993                                  ; 06/11/2014
  1994                                  ; Temporary Code
  1995                                  ;
  1996                                  
  1997                                  bintdstr:
  1998                                  	; EAX = binary number
  1999                                  	; ESI = decimal/numeric string address
  2000                                  	; EBX = divisor (10)
  2001                                  	; ECX = string length (<=10)
  2002 0000170C 01CE                    	add	esi, ecx
  2003                                  btdstr0:
  2004 0000170E 4E                      	dec	esi
  2005 0000170F 31D2                    	xor	edx, edx
  2006 00001711 F7F3                    	div	ebx
  2007 00001713 80C230                  	add	dl, 30h
  2008 00001716 8816                    	mov	[esi], dl
  2009 00001718 FEC9                    	dec	cl
  2010 0000171A 740C                    	jz	btdstr2
  2011 0000171C 09C0                    	or	eax, eax
  2012 0000171E 75EE                    	jnz	short btdstr0
  2013                                  btdstr1:
  2014 00001720 4E                      	dec	esi
  2015 00001721 C60620                          mov     byte [esi], 20h ; blank space
  2016 00001724 FEC9                    	dec	cl
  2017 00001726 75F8                    	jnz	short btdstr1
  2018                                  btdstr2:
  2019 00001728 C3                      	retn
  2020                                  
  2021                                  ; Calculate free memory pages on M.A.T.
  2022                                  ; 06/11/2014
  2023                                  ; Temporary Code
  2024                                  ;
  2025                                  
  2026                                  calc_free_mem:
  2027 00001729 31D2                    	xor	edx, edx
  2028                                  	;xor	ecx, ecx
  2029 0000172B 668B0D[60620000]        	mov	cx, [mat_size] ; in pages
  2030 00001732 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2031 00001735 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2032                                  cfm0:
  2033 0000173A AD                      	lodsd
  2034 0000173B 51                      	push	ecx
  2035 0000173C B920000000              	mov	ecx, 32
  2036                                  cfm1:
  2037 00001741 D1E8                    	shr	eax, 1
  2038 00001743 7301                    	jnc	short cfm2
  2039 00001745 42                      	inc	edx
  2040                                  cfm2:
  2041 00001746 E2F9                    	loop	cfm1
  2042 00001748 59                      	pop	ecx
  2043 00001749 E2EF                    	loop	cfm0
  2044 0000174B C3                      	retn
  2045                                  
  2046                                  %include 'diskio.inc'  ; 07/03/2015
  2047                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - DISKIO.INC
  2048                              <1> ; Last Modification: 16/07/2022
  2049                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2050                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2051                              <1> ; ************************************************************************
  2052                              <1> ; Ref: Retro UNIX 386 v1.1 'diskio.inc' modification: 12/07/2022
  2053                              <1> 
  2054                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2055                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2056                              <1> 
  2057                              <1> ; 15/07/2022
  2058                              <1> ;; 06/02/2015
  2059                              <1> ;diskette_io:
  2060                              <1> ;	pushfd
  2061                              <1> ;	push 	cs
  2062                              <1> ;	call 	DISKETTE_IO_1
  2063                              <1> ;	retn
  2064                              <1> 	
  2065                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2066                              <1> ;//////////////////////////////////////////////////////
  2067                              <1> 
  2068                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2069                              <1> ;		Function in AL
  2070                              <1> ;			0 = reset
  2071                              <1> ;			1 = read
  2072                              <1> ;			2 = write
  2073                              <1> ;		Disk drive number in DL
  2074                              <1> ;			0 & 1 = floppy disks	
  2075                              <1> ;			80h .. 83h = hard disks
  2076                              <1> ;		Sector address (LBA) in ECX
  2077                              <1> ;		Buffer address in EBX
  2078                              <1> ;		R/W sector count is (always) 1
  2079                              <1> ;
  2080                              <1> ;		Return:
  2081                              <1> ;			Status in AH (>0 = error code)
  2082                              <1> ;			if CF = 1 -> error code in AH
  2083                              <1> ;			if CF = 0 -> successful
  2084                              <1> ;			AL = undefined
  2085                              <1> ;
  2086                              <1> ;		Modified registers: (only) EAX
  2087                              <1> 
  2088                              <1> ; 10/07/2022
  2089                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2090                              <1> ;		by removing unused IBM PC-AT disk functions)
  2091                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2092                              <1> ; 20/02/2015
  2093                              <1> ; 06/02/2015 (unix386.s)
  2094                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2095                              <1> ;
  2096                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2097                              <1> ;
  2098                              <1> ; ADISK.EQU
  2099                              <1> 
  2100                              <1> ;----- Wait control constants 
  2101                              <1> 
  2102                              <1> ;amount of time to wait while RESET is active.
  2103                              <1> 
  2104                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2105                              <1> 					;at 250 KBS xfer rate.
  2106                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2107                              <1> 
  2108                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2109                              <1> 					;status register to become valid
  2110                              <1> 					;before re-reading.
  2111                              <1> 
  2112                              <1> ;After sending a byte to NEC, status register may remain
  2113                              <1> ;incorrectly set for 24 us.
  2114                              <1> 
  2115                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2116                              <1> 					;RQM low.
  2117                              <1> 
  2118                              <1> ; COMMON.MAC
  2119                              <1> ;
  2120                              <1> ;	Timing macros
  2121                              <1> ;
  2122                              <1> 
  2123                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2124                              <1> 		jmp short $+2
  2125                              <1> %endmacro		
  2126                              <1> 
  2127                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2128                              <1> 		jmp short $+2
  2129                              <1> 		jmp short $+2
  2130                              <1> %endmacro
  2131                              <1> 
  2132                              <1> %macro		NEWIODELAY 0
  2133                              <1> 		out	0EBh,al
  2134                              <1> %endmacro 
  2135                              <1> 
  2136                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2137                              <1> ;;; WAIT_FOR_MEM
  2138                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2139                              <1> ;WAIT_FDU_INT_HI	equ	1
  2140                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2141                              <1> ;;; WAIT_FOR_PORT
  2142                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2143                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2144                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2145                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2146                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2147                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2148                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2149                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2150                              <1> ;;; WAIT_REFRESH
  2151                              <1> ;amount of time to wait for head settle, per unit in parameter
  2152                              <1> ;table = 1 ms.
  2153                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2154                              <1> 
  2155                              <1> 
  2156                              <1> ; //////////////// DISKETTE I/O ////////////////
  2157                              <1> 
  2158                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2159                              <1> 
  2160                              <1> ;----------------------------------------
  2161                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2162                              <1> ;----------------------------------------
  2163                              <1> 
  2164                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2165                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2166                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2167                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2168                              <1> 
  2169                              <1> ;----------------------------------------
  2170                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2171                              <1> ;-------------------------------------------------------------------------------
  2172                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2173                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2174                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2175                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2176                              <1> 
  2177                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2178                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2179                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2180                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2181                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2182                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2183                              <1> 
  2184                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2185                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2186                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2187                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2188                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2189                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2190                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2191                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2192                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2193                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2194                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2195                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2196                              <1> 
  2197                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2198                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2199                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2200                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2201                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2202                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2203                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2204                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2205                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2206                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2207                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2208                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2209                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2210                              <1> 
  2211                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2212                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2213                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2214                              <1> 
  2215                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2216                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2217                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2218                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2219                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2220                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2221                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2222                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2223                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2224                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2225                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2226                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2227                              <1> 
  2228                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2229                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2230                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2231                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2232                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2233                              <1> 
  2234                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2235                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2236                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2237                              <1> INTA01		EQU	021H		; 8259 PORT
  2238                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2239                              <1> INTB01		EQU	0A1H		;
  2240                              <1> 
  2241                              <1> ;-------------------------------------------------------------------------------
  2242                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2243                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2244                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2245                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2246                              <1> ;-------------------------------------------------------------------------------
  2247                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2248                              <1> 
  2249                              <1> ;-------------------------------------------------------------------------------
  2250                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2251                              <1> 
  2252                              <1> ; 10/07/2022
  2253                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2254                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2255                              <1> ; (unix386.s <-- dsectrm2.s)
  2256                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2257                              <1> 
  2258                              <1> ; 10/12/2014
  2259                              <1> ;
  2260                              <1> ;int40h:
  2261                              <1> ;	pushf
  2262                              <1> ;	push 	cs
  2263                              <1> ;	;cli
  2264                              <1> ;	call 	DISKETTE_IO_1
  2265                              <1> ;	retn
  2266                              <1> 
  2267                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2268                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2269                              <1> ;
  2270                              <1> 
  2271                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2272                              <1> ; DISKETTE I/O
  2273                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2274                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2275                              <1> ; INPUT
  2276                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2277                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2278                              <1> ;		ON ALL DRIVES
  2279                              <1> ;------------------------------------------------------------------------------- 
  2280                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2281                              <1> ;-------------------------------------------------------------------------------
  2282                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2283                              <1> ;-------------------------------------------------------------------------------
  2284                              <1> ;
  2285                              <1> ;	REGISTERS FOR READ/WRITE
  2286                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2287                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2288                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2289                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2290                              <1> ;		320/360	320/360	    0-39
  2291                              <1> ;		320/360	1.2M	    0-39
  2292                              <1> ;		1.2M	1.2M	    0-79
  2293                              <1> ;		720K	720K	    0-79
  2294                              <1> ;		1.44M	1.44M	    0-79	
  2295                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2296                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2297                              <1> ;		320/360	320/360	     1-8/9
  2298                              <1> ;		320/360	1.2M	     1-8/9
  2299                              <1> ;		1.2M	1.2M	     1-15
  2300                              <1> ;		720K	720K	     1-9
  2301                              <1> ;		1.44M	1.44M	     1-18		
  2302                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2303                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2304                              <1> ;		320/360	320/360	        8/9
  2305                              <1> ;		320/360	1.2M	        8/9
  2306                              <1> ;		1.2M	1.2M		15
  2307                              <1> ;		720K	720K		9
  2308                              <1> ;		1.44M	1.44M		18
  2309                              <1> ;
  2310                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2311                              <1> ;
  2312                              <1> ;-------------------------------------------------------------------------------
  2313                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2314                              <1> ;	AH = STATUS OF OPERATION
  2315                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2316                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2317                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2318                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2319                              <1> ;	FOR READ/WRITE/VERIFY
  2320                              <1> ;		DS,BX,DX,CX PRESERVED
  2321                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2322                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2323                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2324                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2325                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2326                              <1> ;-------------------------------------------------------------------------------
  2327                              <1> ;
  2328                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2329                              <1> ;
  2330                              <1> ;   -----------------------------------------------------------------
  2331                              <1> ;   |       |       |       |       |       |       |       |       |
  2332                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2333                              <1> ;   |       |       |       |       |       |       |       |       |
  2334                              <1> ;   -----------------------------------------------------------------
  2335                              <1> ;	|	|	|	|	|	|	|	|
  2336                              <1> ;	|	|	|	|	|	-----------------
  2337                              <1> ;	|	|	|	|	|		|
  2338                              <1> ;	|	|	|	|    RESERVED		|
  2339                              <1> ;	|	|	|	|		  PRESENT STATE
  2340                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2341                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2342                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2343                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2344                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2345                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2346                              <1> ;	|	|	|	|	110: RESERVED
  2347                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2348                              <1> ;	|	|	|	|
  2349                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2350                              <1> ;	|	|	|
  2351                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2352                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2353                              <1> ;	|	|
  2354                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2355                              <1> ;
  2356                              <1> ;						00: 500 KBS
  2357                              <1> ;						01: 300 KBS
  2358                              <1> ;						10: 250 KBS
  2359                              <1> ;						11: RESERVED
  2360                              <1> ;
  2361                              <1> ;
  2362                              <1> 
  2363                              <1> struc MD
  2364 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2365 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2366 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2367 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2368 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2369 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2370 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2371 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2372 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2373 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2374 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2375 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2376 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2377                              <1> endstruc
  2378                              <1> 
  2379                              <1> BIT7OFF	EQU	7FH
  2380                              <1> BIT7ON	EQU	80H
  2381                              <1> 
  2382                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2383                              <1> ;		Function in AL
  2384                              <1> ;			0 = reset
  2385                              <1> ;			1 = read
  2386                              <1> ;			2 = write
  2387                              <1> ;		Disk drive number in DL
  2388                              <1> ;			0 & 1 = floppy disks	
  2389                              <1> ;			80h .. 83h = hard disks
  2390                              <1> ;		Sector address (LBA) in ECX
  2391                              <1> ;		Buffer address in EBX
  2392                              <1> ;		R/W sector count is (always) 1
  2393                              <1> ;
  2394                              <1> ;		Return:
  2395                              <1> ;			Status in AH (>0 = error code)
  2396                              <1> ;			if CF = 1 -> error code in AH
  2397                              <1> ;			if CF = 0 -> successful
  2398                              <1> ;			AL = undefined
  2399                              <1> ;
  2400                              <1> ;		Modified registers: (only) EAX
  2401                              <1> 
  2402                              <1> ; 11/07/2022
  2403                              <1> ;;int13h: ; 16/02/2015
  2404                              <1> ;; 16/02/2015 - 21/02/2015
  2405                              <1> ;int40h:
  2406                              <1> ;	pushfd
  2407                              <1> ;	push 	cs
  2408                              <1> ;	call 	DISKETTE_IO_1
  2409                              <1> ;	retn	
  2410                              <1> 
  2411                              <1> DISKETTE_IO_1:
  2412                              <1> 
  2413                              <1> 	;sti				; INTERRUPTS BACK ON
  2414                              <1> 	; 11/07/2022
  2415                              <1> 	; save registers
  2416 0000174C 55                  <1> 	push	ebp			; ANY
  2417                              <1> 
  2418                              <1> 	; 11/07/2022
  2419                              <1> 	;push	edi			; ANY
  2420                              <1> 	;push	edx			; DRIVE NUMBER (DL)
  2421                              <1> 	;push	ebx			; BUFFER ADDRESS
  2422                              <1> 	;push	ecx			; SECTOR ADDRESS (LBA)
  2423                              <1> 	;push	esi			; ANY
  2424                              <1> 
  2425                              <1> 	; 11/07/2022
  2426 0000174D 89DD                <1> 	mov	ebp, ebx ; buffer address
  2427 0000174F C605[CC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS
  2428 00001756 0FB6FA              <1> 	movzx	edi, dl ; drive number (0 or 1)
  2429                              <1> 	
  2430 00001759 08C0                <1> 	or	al, al			; RESET ?
  2431 0000175B 7507                <1> 	jnz	short DISKETTE_RW_1	; NO
  2432                              <1> 
  2433 0000175D E84F010000          <1> 	call	DSK_RESET
  2434                              <1> 
  2435 00001762 EB37                <1> 	jmp	short DISKETTE_RW_2	
  2436                              <1> 
  2437                              <1> DISKETTE_RW_1:
  2438                              <1> 	; 12/07/2022
  2439                              <1> 	; 11/07/2022
  2440                              <1> 	; ecx = sector address (LBA, < 2880)
  2441                              <1> 	; ebp = buffer address
  2442                              <1> 	; edi = drive number (0 or 1)
  2443                              <1> 	;  al = function (read = 1 or write = 2)
  2444                              <1> 
  2445 00001764 88C2                <1> 	mov	dl, al ; *
  2446                              <1> convert_to_chs:
  2447                              <1> 	;;;
  2448 00001766 B004                <1> 	mov	al, 4 ; MD.SEC_TRK ; sector per track (drv.spt)
  2449 00001768 E8F2050000          <1> 	call	GET_PARM
  2450                              <1> 	; 12/07/2022
  2451 0000176D 88E6                <1> 	mov	dh, ah ; spt
  2452 0000176F 89C8                <1> 	mov	eax, ecx ; sector address (LBA) 
  2453 00001771 F6F6                <1> 	div	dh  ; AX/DH
  2454 00001773 88E1                <1> 	mov	cl, ah ; sector number - 1
  2455 00001775 FEC1                <1> 	inc	cl  ; sector number (1 based)
  2456 00001777 28ED                <1> 	sub	ch, ch ; head = 0 
  2457                              <1> 	; heads = 2
  2458 00001779 D0E8                <1> 	shr	al, 1 ; al = al/2
  2459 0000177B 80D500              <1> 	adc	ch, 0 ; head = 1 or head = 0
  2460 0000177E C1E110              <1> 	shl	ecx, 16
  2461 00001781 88C1                <1> 	mov	cl, al ; track (cylinder)
  2462 00001783 88D5                <1> 	mov	ch, dl ; function number 
  2463 00001785 89CE                <1> 	mov	esi, ecx ; byte 0 = track, byte 1 = function
  2464                              <1> 			 ; byte 2 = sector, byte 3 = head
  2465 00001787 C1C610              <1> 	rol	esi, 16
  2466                              <1> 			 ; byte 0 = sector, byte 1 = head
  2467                              <1> 			 ; byte 2 = track, byte 3 = function		
  2468                              <1> 	;;; 
  2469 0000178A 80FA02              <1> 	cmp	dl, 2 ; *
  2470 0000178D 7407                <1> 	je	short DISKETTE_W
  2471                              <1> DISKETTE_R:	
  2472                              <1> 	; dl = 1 ; *
  2473 0000178F E809000000          <1> 	call	DSK_READ
  2474 00001794 EB05                <1> 	jmp	short DISKETTE_RW_2
  2475                              <1> DISKETTE_W:
  2476 00001796 E80F000000          <1> 	call	DSK_WRITE
  2477                              <1> DISKETTE_RW_2:
  2478                              <1> 	; 11/07/2022
  2479                              <1> 	; Restore registers
  2480                              <1> 	;pop	esi
  2481                              <1> 	;pop	ecx
  2482                              <1> 	;pop	ebx
  2483                              <1> 	;pop	edx
  2484                              <1> 	;pop	edi
  2485                              <1> 
  2486                              <1> 	; 11/07/2022
  2487 0000179B 5D                  <1> 	pop	ebp
  2488 0000179C C3                  <1> 	retn
  2489                              <1> 
  2490                              <1> ;-------------------------------------------------------------------------------
  2491                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2492                              <1> ;	DISKETTE READ.
  2493                              <1> ;
  2494                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2495                              <1> ;		SI-HI	: HEAD #
  2496                              <1> ;		SI-LOW	: # OF SECTORS
  2497                              <1> ;		ES	: BUFFER SEGMENT
  2498                              <1> ;		[BP]	: SECTOR #
  2499                              <1> ;		[BP+1]	: TRACK #
  2500                              <1> ;		[BP+2]	: BUFFER OFFSET
  2501                              <1> ;
  2502                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2503                              <1> ;-------------------------------------------------------------------------------
  2504                              <1> 
  2505                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2506                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2507                              <1> 
  2508                              <1> DSK_READ:
  2509 0000179D 8025[CA620000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2510 000017A4 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2511                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2512                              <1> 	;retn
  2513 000017A8 EB0B                <1> 	jmp	short RD_WR_VF
  2514                              <1> 
  2515                              <1> ;-------------------------------------------------------------------------------
  2516                              <1> ; DISK_WRITE	(AH = 02H)
  2517                              <1> ;	DISKETTE WRITE.
  2518                              <1> ;
  2519                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2520                              <1> ;		SI-HI	: HEAD #
  2521                              <1> ;		SI-LOW	: # OF SECTORS
  2522                              <1> ;		ES	: BUFFER SEGMENT
  2523                              <1> ;		[BP]	: SECTOR #
  2524                              <1> ;		[BP+1]	: TRACK #
  2525                              <1> ;		[BP+2]	: BUFFER OFFSET
  2526                              <1> ;
  2527                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2528                              <1> ;-------------------------------------------------------------------------------
  2529                              <1> 
  2530                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2531                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2532                              <1> 
  2533                              <1> DSK_WRITE:
  2534 000017AA 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2535 000017AE 800D[CA620000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2536                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2537                              <1> 	;;retn
  2538                              <1> 	;jmp	short RD_WR_VF
  2539                              <1> 
  2540                              <1> ;-------------------------------------------------------------------------------
  2541                              <1> ; RD_WR_VF
  2542                              <1> ;	COMMON READ, WRITE
  2543                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2544                              <1> ;
  2545                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2546                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2547                              <1> ;
  2548                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2549                              <1> ;-------------------------------------------------------------------------------
  2550                              <1> 
  2551                              <1> RD_WR_VF:
  2552                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2553 000017B5 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2554 000017B6 E8CF010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2555 000017BB E831020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2556 000017C0 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2557                              <1> DO_AGAIN:
  2558 000017C1 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2559 000017C2 E86B020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2560 000017C7 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2561                              <1> 	; 24/12/2021
  2562 000017C8 7305                <1> 	jnc	short RWV
  2563 000017CA E9B8000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2564                              <1> RWV:
  2565 000017CF 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2566 000017D0 8AB7[D7620000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2567 000017D6 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2568 000017D9 E878050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2569                              <1> 	; 20/02/2015
  2570 000017DE 7445                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2571 000017E0 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2572 000017E2 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2573 000017E4 F687[D7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2574 000017EB 740F                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2575                              <1> 	;mov	al, 2			; CHANGE TO 1.2M
  2576                              <1> 	; 12/07/2022
  2577 000017ED FEC0                <1> 	inc	al  ; al = 2
  2578 000017EF EB0B                <1> 	jmp	short RWV_2
  2579                              <1> RWV_1:
  2580                              <1> 	; 12/07/2022
  2581                              <1> 	;jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2582 000017F1 F687[D7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2583 000017F8 7502                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2584 000017FA B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2585                              <1> 	; 12/07/2022
  2586                              <1> 	;jmp	short RWV_3
  2587                              <1> RWV_2:
  2588                              <1> 	; 12/07/2022
  2589                              <1> 	;or	al, al			; TEST FOR NO DRIVE
  2590                              <1> 	;jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2591                              <1> RWV_3:
  2592                              <1> 	; 12/07/2022
  2593                              <1> 	;mov	dl, al	; 11/07/2022
  2594 000017FC E823010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2595 00001801 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2596                              <1> 
  2597                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2598                              <1> 
  2599 00001803 57                  <1> 	push	edi			; SAVE DRIVE #
  2600                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2601 00001804 BB[EC5C0000]        <1> 	mov	ebx, DR_TYPE
  2602                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2603 00001809 B106                <1> 	mov	cl, DR_CNT
  2604                              <1> RWV_DR_SEARCH:
  2605                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2606 0000180B 8A23                <1> 	mov	ah, [ebx]
  2607 0000180D 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2608 00001810 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2609                              <1> 	; 12/07/2022
  2610                              <1> 	;cmp	dl, ah ; 11/07/2022
  2611 00001812 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2612                              <1> RWV_DR_FND:
  2613                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2614 00001814 43                  <1> 	inc	ebx
  2615 00001815 8B3B                <1> 	mov	edi, [ebx]
  2616 00001817 4B                  <1> 	dec	ebx
  2617                              <1> RWV_MD_SEARH:
  2618 00001818 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2619 0000181B 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2620                              <1> RWV_NXT_MD:
  2621 0000181D 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2622                              <1> 	;loop	RWV_DR_SEARCH
  2623 00001820 FEC9                <1> 	dec	cl
  2624 00001822 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2625 00001824 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2626                              <1> 
  2627                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2628                              <1> 
  2629                              <1> RWV_ASSUME:
  2630 00001825 BB[0A5D0000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2631 0000182A F687[D7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2632 00001831 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2633 00001833 BB[245D0000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2634 00001838 EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2635                              <1> 
  2636                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2637                              <1> 	 			
  2638                              <1> RWV_MD_FND:
  2639 0000183A 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2640 0000183C 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2641                              <1> 	
  2642                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2643                              <1> 
  2644                              <1> RWV_MD_FND1:
  2645 0000183D E828010000          <1> 	call	SEND_SPEC_MD
  2646 00001842 E857020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2647 00001847 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2648 00001849 E832020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2649                              <1> RWV_DBL:
  2650 0000184E 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2651 0000184F E860040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2652 00001854 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2653 00001855 7223                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2654                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2655                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2656                              <1> 	; 08/07/2022
  2657 00001857 8B0424              <1> 	mov	eax, [esp]
  2658 0000185A 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2659 0000185B E851020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2660 00001860 5B                  <1> 	pop	ebx
  2661 00001861 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2662 00001862 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2663 00001864 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2664 00001865 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2665 00001866 E8A3020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2666 0000186B 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2667 0000186C 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2668 0000186E E8CC020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2669 00001873 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2670 00001875 E813030000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2671                              <1> CHK_RET:
  2672 0000187A E8B2030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2673 0000187F 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2674 00001880 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2675 00001882 E93AFFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2676                              <1> RWV_END:
  2677 00001887 E85D030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2678 0000188C E8EE030000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2679                              <1> RWV_BAC:
  2680                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2681                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2682                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2683                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2684                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2685                              <1> 	;;retn
  2686                              <1> 	;jmp	SETUP_END
  2687                              <1> 
  2688                              <1> ;-------------------------------------------------------------------------------
  2689                              <1> ; SETUP_END
  2690                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2691                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2692                              <1> ;
  2693                              <1> ; ON EXIT:
  2694                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2695                              <1> ;-------------------------------------------------------------------------------
  2696                              <1> SETUP_END:
  2697                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2698                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2699                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2700 00001891 50                  <1> 	push	eax ; 24/12/2021
  2701 00001892 B002                <1> 	mov	al, 2 ; 08/07/2022
  2702 00001894 E8C6040000          <1> 	call	GET_PARM
  2703 00001899 8825[CB620000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2704                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2705 0000189F 58                  <1> 	pop	eax ; 24/12/2021
  2706 000018A0 8A25[CC620000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2707 000018A6 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2708 000018A8 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2709 000018AA 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2710                              <1> ;NUN_ERR: 
  2711 000018AC 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2712 000018AF F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2713                              <1> NUN_ERR:
  2714 000018B0 C3                  <1> 	retn
  2715                              <1> 
  2716                              <1> ;-------------------------------------------------------------------------------
  2717                              <1> ; DISK_RESET	(AH = 00H)	
  2718                              <1> ;		RESET THE DISKETTE SYSTEM.
  2719                              <1> ;
  2720                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2721                              <1> ;-------------------------------------------------------------------------------
  2722                              <1> DSK_RESET:
  2723                              <1> 	; 12/07/2022
  2724                              <1> 	; 11/07/2022
  2725                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2726 000018B1 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2727 000018B5 FA                  <1> 	cli				; NO INTERRUPTS
  2728 000018B6 A0[CA620000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2729 000018BB 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2730 000018BD C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2731                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2732 000018C0 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2733 000018C2 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2734 000018C3 C605[C9620000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2735                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2736                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2737                              <1> 					;      PULSE WIDTH)
  2738                              <1> 	; 19/12/2014
  2739                              <1> 	NEWIODELAY
  2133 000018CA E6EB                <2>  out 0EBh,al
  2740                              <1> 
  2741                              <1> 	; 17/12/2014 
  2742                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2743 000018CC B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2744                              <1> wdw1:
  2745                              <1> 	NEWIODELAY   ; 27/02/2015
  2133 000018D1 E6EB                <2>  out 0EBh,al
  2746 000018D3 E2FC                <1> 	loop	wdw1
  2747                              <1> 	;
  2748 000018D5 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2749 000018D7 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2750                              <1> 	; 16/12/2014
  2751                              <1> 	IODELAY
  2128 000018D8 EB00                <2>  jmp short $+2
  2129 000018DA EB00                <2>  jmp short $+2
  2752                              <1> 	;
  2753                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2754 000018DC E879060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2755 000018E1 7238                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2756                              <1> 	;mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2757                              <1> 	; 12/07/2022
  2758                              <1> 	;xor	ecx, ecx
  2759 000018E3 30ED                <1> 	xor	ch, ch
  2760 000018E5 B1C0                <1> 	mov	cl, 11000000b
  2761                              <1> NXT_DRV:
  2762                              <1> 	; 24/12/2021
  2763 000018E7 51                  <1> 	push	ecx			; SAVE FOR CALL
  2764 000018E8 B8[1A190000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2765 000018ED 50                  <1> 	push	eax			;
  2766 000018EE B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2767 000018F0 E85B050000          <1> 	call	NEC_OUTPUT
  2768 000018F5 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2769 000018F6 E88E060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2770                              <1> 	; 24/12/2021
  2771 000018FB 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2772 000018FC 721D                <1> 	jc	short DR_ERR		; ERROR RETURN
  2773 000018FE 3A0D[CD620000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2774 00001904 7515                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2775 00001906 FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2776 00001908 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2777 0000190B 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2778                              <1> 	;
  2779 0000190D E82F000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2780                              <1> RESBAC:
  2781 00001912 E87AFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2782                              <1> 	
  2783                              <1> 	; 11/07/2022
  2784                              <1> 	; CF = 1 -> error (error code in AH)
  2785                              <1> 	; CF = 0 -> OK
  2786                              <1> 	
  2787                              <1> 	;; 24/12/2021
  2788                              <1> 	;mov	ebx, esi		; GET SAVED AL TO BL
  2789                              <1> 	;; 11/07/2022
  2790                              <1> 	;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 
  2791                              <1> 	;rol	ebx, 8
  2792                              <1> 	; bl = function (reset = 0)
  2793                              <1> 	;
  2794                              <1> 	;mov	al, bl			; PUT BACK FOR RETURN
  2795                              <1> 	
  2796                              <1> 	; 11/07/2022  
  2797 00001917 B000                <1> 	mov	al, 0	; (reset function = 0)
  2798                              <1> 
  2799 00001919 C3                  <1> 	retn
  2800                              <1> 
  2801                              <1> DR_POP_ERR:
  2802                              <1> 	; 24/12/2021
  2803 0000191A 59                  <1> 	pop	ecx			; CLEAR STACK
  2804                              <1> DR_ERR:
  2805 0000191B 800D[CC620000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2806 00001922 EBEE                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2807                              <1> 
  2808                              <1> ;-------------------------------------------------------------------------------
  2809                              <1> ; FNC_ERR
  2810                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2811                              <1> ;	SET BAD COMMAND IN STATUS.
  2812                              <1> ;
  2813                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2814                              <1> ;-------------------------------------------------------------------------------
  2815                              <1> 
  2816                              <1> 	; 11/07/2022 - not needed (because diskio is used by kernel only)
  2817                              <1> 	
  2818                              <1> ;FNC_ERR:				; INVALID FUNCTION REQUEST
  2819                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2820                              <1> ;	; 24/12/2021
  2821                              <1> ;	mov	eax, esi		; RESTORE AL
  2822                              <1> ;	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2823                              <1> ;	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2824                              <1> ;	stc				; SET CARRY INDICATING ERROR
  2825                              <1> ;	retn
  2826                              <1> 
  2827                              <1> 
  2828                              <1> ;----------------------------------------------------------------
  2829                              <1> ; DR_TYPE_CHECK							:
  2830                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2831                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2832                              <1> ; ON ENTRY:							:
  2833                              <1> ;	AL = DRIVE TYPE						:
  2834                              <1> ; ON EXIT:							:
  2835                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2836                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2837                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2838                              <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 			:
  2839                              <1> ;----------------------------------------------------------------
  2840                              <1> DR_TYPE_CHECK:
  2841                              <1> 	; 12/07/2022
  2842                              <1> 	; 11/07/2022
  2843                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2844                              <1> 	; 24/12/2021
  2845                              <1> 	;push	eax ; 11/07/2022
  2846                              <1> 	;push	ecx ; 08/07/2022
  2847                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2848 00001924 BB[EC5C0000]        <1> 	mov	ebx, DR_TYPE
  2849                              <1> 	;;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2850                              <1> 	;mov	cl, DR_CNT
  2851 00001929 B406                <1> 	mov	ah, DR_CNT ; 11/07/2022
  2852                              <1> TYPE_CHK:	
  2853                              <1> 	;;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2854                              <1> 	;mov	ah, [ebx]
  2855                              <1> 	;cmp	al, ah			; DRIVE TYPE MATCH?
  2856 0000192B 3A03                <1> 	cmp	al, [ebx] ; 11/07/2022
  2857 0000192D 740E                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2858                              <1> 	; 16/02/2015 (32 bit address modification)
  2859 0000192F 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2860                              <1> 	;loop	TYPE_CHK
  2861                              <1> 	;dec	cl
  2862 00001932 FECC                <1> 	dec	ah ; 11/07/2022
  2863 00001934 75F5                <1> 	jnz	short TYPE_CHK
  2864                              <1> 	;
  2865 00001936 BB[4B5D0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2866                              <1> 					; Default for GET_PARM (11/12/2014)
  2867                              <1> 	;
  2868 0000193B F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2869                              <1> 	;jmp	short TYPE_RTN
  2870                              <1> 	; 12/07/2022
  2871 0000193C C3                  <1> 	retn
  2872                              <1> DR_TYPE_VALID:
  2873                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2874 0000193D 43                  <1> 	inc	ebx
  2875 0000193E 8B1B                <1> 	mov	ebx, [ebx]
  2876                              <1> TYPE_RTN:
  2877                              <1> 	;pop	ecx ; 08/07/2022
  2878                              <1> 	; 24/12/2021
  2879                              <1> 	;pop	eax ; 11/07/2022
  2880 00001940 C3                  <1> 	retn		
  2881                              <1> 
  2882                              <1> ;----------------------------------------------------------------
  2883                              <1> ; SEND_SPEC							:
  2884                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2885                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2886                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2887                              <1> ; ON EXIT:	NONE						:	
  2888                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2889                              <1> ;----------------------------------------------------------------		
  2890                              <1> SEND_SPEC:
  2891                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2892 00001941 50                  <1> 	push	eax			; SAVE EAX
  2893 00001942 B8[68190000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2894 00001947 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2895 00001948 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2896 0000194A E801050000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2897                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2898 0000194F 28C0                <1> 	sub	al, al ; 08/07/2022
  2899 00001951 E809040000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2900 00001956 E8F5040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2901                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2902 0000195B B001                <1> 	mov	al, 1 ; 08/07/2022
  2903 0000195D E8FD030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2904 00001962 E8E9040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2905 00001967 58                  <1> 	pop	eax			; POP ERROR RETURN
  2906                              <1> SPECBAC:
  2907 00001968 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2908 00001969 C3                  <1> 	retn
  2909                              <1> 
  2910                              <1> ;----------------------------------------------------------------
  2911                              <1> ; SEND_SPEC_MD							:
  2912                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2913                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  2914                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  2915                              <1> ; ON EXIT:	NONE						:	
  2916                              <1> ; REGISTERS ALTERED: AX						:
  2917                              <1> ;----------------------------------------------------------------		
  2918                              <1> SEND_SPEC_MD:
  2919 0000196A 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  2920 0000196B B8[88190000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2921 00001970 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2922 00001971 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  2923 00001973 E8D8040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2924 00001978 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2925 0000197A E8D1040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2926 0000197F 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2927 00001982 E8C9040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2928 00001987 58                  <1> 	POP	eAX			; POP ERROR RETURN
  2929                              <1> SPEC_ESBAC:
  2930 00001988 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  2931 00001989 C3                  <1> 	RETn
  2932                              <1> 
  2933                              <1> ;-------------------------------------------------------------------------------
  2934                              <1> ; XLAT_NEW  
  2935                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  2936                              <1> ;	MODE TO NEW ARCHITECTURE.
  2937                              <1> ;
  2938                              <1> ; ON ENTRY:	EDI = DRIVE #
  2939                              <1> ;-------------------------------------------------------------------------------
  2940                              <1> XLAT_NEW:
  2941                              <1> 	; 11/07/2022
  2942                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2943                              <1> 	;cmp	edi, 1				; VALID DRIVE
  2944                              <1> 	;ja	short XN_OUT			; IF INVALID BACK
  2945                              <1> 	;
  2946 0000198A 80BF[D7620000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  2947 00001991 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  2948                              <1> 	;
  2949                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2950                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  2951                              <1> 	;or	cl, cl
  2952                              <1> 	;jz	short XN_0  ; 08/07/2022
  2953                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  2954                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2955                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  2956                              <1> ;XN_0:	
  2957                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  2958                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  2959                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  2960                              <1> XN_OUT:
  2961 00001993 C3                  <1> 	retn
  2962                              <1> DO_DET:
  2963                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  2964                              <1> 	;;retn
  2965                              <1> 	;jmp	DRIVE_DET
  2966                              <1> 
  2967                              <1> ;-------------------------------------------------------------------------------
  2968                              <1> ; DRIVE_DET
  2969                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  2970                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  2971                              <1> ; ON ENTRY:	EDI = DRIVE #
  2972                              <1> ;-------------------------------------------------------------------------------
  2973                              <1> DRIVE_DET:
  2974                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2975 00001994 E801040000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  2976 00001999 E86A050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  2977 0000199E 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  2978 000019A0 B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  2979 000019A2 E8E2040000          <1> 	call	SEEK
  2980 000019A7 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  2981 000019A9 B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  2982                              <1> SK_GIN:
  2983 000019AB FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  2984                              <1> 	;push	cx		
  2985                              <1> 	; 24/12/2021
  2986 000019AD 51                  <1> 	push	ecx			; SAVE TRACK
  2987 000019AE E8D6040000          <1> 	call	SEEK
  2988 000019B3 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  2989 000019B5 B8[EF190000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  2990 000019BA 50                  <1> 	push	eax
  2991 000019BB B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  2992 000019BD E88E040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2993                              <1> 	; 08/07/2022
  2994 000019C2 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  2995 000019C4 88C4                <1> 	mov	ah, al			; AH = DRIVE
  2996 000019C6 E885040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2997 000019CB E8B9050000          <1> 	call	RESULTS			; GO GET STATUS
  2998 000019D0 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  2999                              <1> 	;pop	cx			; RESTORE TRACK
  3000                              <1> 	; 24/12/2021
  3001 000019D1 59                  <1> 	pop	ecx
  3002 000019D2 F605[CD620000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  3003 000019D9 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  3004 000019DB 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  3005 000019DD 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  3006                              <1> 
  3007                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  3008                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  3009                              <1> 
  3010 000019DF 808F[D7620000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  3011 000019E6 C3                  <1> 	retn				; ALL INFORMATION SET
  3012                              <1> IS_80:
  3013 000019E7 808F[D7620000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3014                              <1> DD_BAC:
  3015 000019EE C3                  <1> 	retn
  3016                              <1> POP_BAC:
  3017                              <1> 	;pop	cx			; THROW AWAY
  3018                              <1> 	; 24/12/2021
  3019 000019EF 59                  <1> 	pop	ecx
  3020 000019F0 C3                  <1> 	retn
  3021                              <1> 
  3022                              <1> ;-------------------------------------------------------------------------------
  3023                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3024                              <1> ;-------------------------------------------------------------------------------
  3025                              <1> SETUP_STATE:
  3026                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3027 000019F1 F687[D7620000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3028 000019F8 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3029 000019FA 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3030 000019FE F687[D7620000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3031 00001A05 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3032 00001A07 F687[D7620000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3033 00001A0E 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3034 00001A10 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3035                              <1> AX_SET:	
  3036 00001A14 80A7[D7620000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3037 00001A1B 08A7[D7620000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3038 00001A21 8025[D4620000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3039 00001A28 C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3040 00001A2B 0805[D4620000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3041                              <1> J1C:	
  3042 00001A31 C3                  <1> 	retn
  3043                              <1> 
  3044                              <1> ;-------------------------------------------------------------------------------
  3045                              <1> ; MED_CHANGE	
  3046                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3047                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3048                              <1> ;
  3049                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3050                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3051                              <1> ;-------------------------------------------------------------------------------
  3052                              <1> MED_CHANGE:
  3053                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3054 00001A32 E8AA050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3055 00001A37 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3056 00001A39 80A7[D7620000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3057                              <1> 
  3058                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3059                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3060                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3061                              <1> 
  3062 00001A40 89F9                <1> 	mov	ecx, edi		; CL = DRIVE #
  3063 00001A42 B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3064 00001A44 D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3065 00001A46 F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3066 00001A48 FA                  <1> 	cli				; NO INTERRUPTS
  3067 00001A49 2005[CA620000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3068 00001A4F FB                  <1> 	sti				; INTERRUPTS ENABLED
  3069 00001A50 E845030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3070                              <1> 
  3071                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3072                              <1> 
  3073 00001A55 E857FEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3074 00001A5A B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3075 00001A5C E828040000          <1> 	call	SEEK			; ISSUE SEEK
  3076 00001A61 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3077 00001A63 E821040000          <1> 	call	SEEK			; ISSUE SEEK
  3078 00001A68 C605[CC620000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3079                              <1> OK1:
  3080 00001A6F E86D050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3081 00001A74 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3082                              <1> OK4:
  3083 00001A76 C605[CC620000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3084                              <1> OK2:		
  3085 00001A7D F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3086 00001A7E C3                  <1> 	retn
  3087                              <1> MC_OUT:
  3088                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3089 00001A7F C3                  <1> 	retn
  3090                              <1> 
  3091                              <1> ;-------------------------------------------------------------------------------
  3092                              <1> ; SEND_RATE
  3093                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3094                              <1> ; ON ENTRY:	EDI = DRIVE #
  3095                              <1> ; ON EXIT:	NONE
  3096                              <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022
  3097                              <1> ;-------------------------------------------------------------------------------
  3098                              <1> SEND_RATE:
  3099                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5
  3100                              <1> 	;push	ax			; SAVE REG.
  3101                              <1> 	; 24/12/2021
  3102                              <1> 	;push	eax ; 11/07/2022
  3103 00001A80 8025[D4620000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3104 00001A87 8A87[D7620000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3105 00001A8D 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3106 00001A8F 0805[D4620000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3107 00001A95 C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3108 00001A98 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3109 00001A9C EE                  <1> 	out	dx, al
  3110                              <1> 	;pop	ax			; RESTORE REG.
  3111                              <1> 	; 24/12/2021
  3112                              <1> 	;pop	eax ; 11/07/2022
  3113 00001A9D C3                  <1> 	retn
  3114                              <1> 
  3115                              <1> ;-------------------------------------------------------------------------------
  3116                              <1> ; CHK_LASTRATE
  3117                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3118                              <1> ; ON ENTRY:
  3119                              <1> ;	EDI = DRIVE #
  3120                              <1> ; ON EXIT:
  3121                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3122                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3123                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022
  3124                              <1> ;-------------------------------------------------------------------------------
  3125                              <1> CHK_LASTRATE:
  3126                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3127                              <1> 	;push	ax			; SAVE REG.
  3128                              <1> 	; 24/12/2021
  3129                              <1> 	;push	eax ; 11/07/2022
  3130 00001A9E 8A25[D4620000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3131                              <1> 					; GET LAST DATA RATE SELECTED
  3132 00001AA4 8A87[D7620000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3133 00001AAA 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3134 00001AAE 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3135                              <1> 					; ZF = 1 RATE IS THE SAME
  3136                              <1> 	;pop	ax			; RESTORE REG.
  3137                              <1> 	; 24/12/2021
  3138                              <1> 	;pop	eax ; 11/07/2022
  3139 00001AB0 C3                  <1> 	retn
  3140                              <1> 
  3141                              <1> ;-------------------------------------------------------------------------------
  3142                              <1> ; DMA_SETUP
  3143                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3144                              <1> ;
  3145                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3146                              <1> ;
  3147                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3148                              <1> ;-------------------------------------------------------------------------------
  3149                              <1> 
  3150                              <1> ; SI = Head #, # of Sectors or DASD Type
  3151                              <1> 
  3152                              <1> ; 22/08/2015
  3153                              <1> ; 08/02/2015 - Protected Mode Modification
  3154                              <1> ; 06/02/2015 - 07/02/2015
  3155                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3156                              <1> ; (DMA Addres = Physical Address)
  3157                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3158                              <1> ;
  3159                              <1> ; 04/02/2016 (clc)
  3160                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3161                              <1> ; 16/12/2014 (IODELAY)
  3162                              <1> 
  3163                              <1> DMA_SETUP:
  3164                              <1> 	; 11/07/2022
  3165                              <1> 	;	ebp = buffer address
  3166                              <1> 	
  3167                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3168                              <1> 	;; 20/02/2015
  3169                              <1> 	;mov	edx, [ebp+4] ; 11/07/2022 ; Buffer address
  3170                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3171                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3172                              <1> 	;jnz	short dma_bnd_err_stc
  3173                              <1> 	; 24/12/2021
  3174 00001AB1 50                  <1> 	push	eax			; DMA command
  3175                              <1> 	;push	edx ; 11/07/2022	; *
  3176                              <1> 	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3177 00001AB2 B003                <1> 	mov	al, 3 ; 08/07/2022
  3178 00001AB4 E8A6020000          <1> 	call	GET_PARM		; 
  3179 00001AB9 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3180                              <1> 	;mov	ax, si			; Sector count
  3181                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3182                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3183                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3184                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3185                              <1> 	; 08/07/2022
  3186                              <1> 	; 24/12/2021
  3187                              <1> 	;mov	edx, esi
  3188 00001ABB 29C0                <1> 	sub	eax, eax
  3189                              <1> 	;mov	ah, dl
  3190                              <1> 	;shr	eax, 1
  3191 00001ABD B080                <1> 	mov	al, 128
  3192 00001ABF D3E0                <1> 	shl	eax, cl
  3193                              <1> 	;
  3194 00001AC1 48                  <1> 	dec	eax			; -1 FOR DMA VALUE
  3195 00001AC2 89C1                <1> 	mov	ecx, eax
  3196                              <1> 	;pop	edx ; 11/07/2022	; *
  3197                              <1> 	; 24/12/2021
  3198 00001AC4 58                  <1> 	pop	eax
  3199                              <1> 	; 08/07/2022
  3200                              <1> 	;cmp	al, 42h
  3201                              <1>         ;jne	short NOT_VERF
  3202                              <1> 	;mov	edx, 0FF0000h
  3203                              <1> 	;jmp	short J33
  3204                              <1> ;NOT_VERF:
  3205                              <1> 	; 11/07/2022
  3206 00001AC5 89EA                <1> 	mov	edx, ebp
  3207                              <1> 	;
  3208 00001AC7 6601CA              <1> 	add	dx, cx			; check for (64K) overflow
  3209 00001ACA 723A                <1> 	jc	short dma_bnd_err
  3210                              <1> 	;
  3211                              <1> 	;sub	dx, cx ; 11/07/2022	; Restore start address
  3212                              <1> J33:
  3213                              <1> 	; 08/07/2022
  3214 00001ACC FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3215 00001ACD E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LA5T F/F
  3216                              <1> 	IODELAY				; WAIT FOR I/O
  2128 00001ACF EB00                <2>  jmp short $+2
  2129 00001AD1 EB00                <2>  jmp short $+2
  3217 00001AD3 E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3218                              <1> 	;mov	eax, edx		; Buffer address
  3219                              <1> 	; 11/07/2022
  3220 00001AD5 89E8                <1> 	mov	eax, ebp ; buffer address
  3221 00001AD7 E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3222                              <1> 	IODELAY				; WAIT FOR I/O
  2128 00001AD9 EB00                <2>  jmp short $+2
  2129 00001ADB EB00                <2>  jmp short $+2
  3223 00001ADD 88E0                <1> 	mov	al, ah
  3224 00001ADF E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3225 00001AE1 C1E810              <1> 	shr	eax, 16
  3226                              <1> 	IODELAY				; I/O WAIT STATE
  2128 00001AE4 EB00                <2>  jmp short $+2
  2129 00001AE6 EB00                <2>  jmp short $+2
  3227 00001AE8 E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3228                              <1> 	IODELAY
  2128 00001AEA EB00                <2>  jmp short $+2
  2129 00001AEC EB00                <2>  jmp short $+2
  3229                              <1> 	;mov	ax, cx			; Byte count - 1
  3230 00001AEE 88C8                <1> 	mov	al, cl
  3231 00001AF0 E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3232                              <1> 	IODELAY				; WAIT FOR I/O
  2128 00001AF2 EB00                <2>  jmp short $+2
  2129 00001AF4 EB00                <2>  jmp short $+2
  3233                              <1> 	;mov	al, ah
  3234 00001AF6 88E8                <1> 	mov	al, ch
  3235 00001AF8 E605                <1> 	OUT	DMA+5, al		; HIGH BYTE OF COUNT
  3236                              <1> 	IODELAY
  2128 00001AFA EB00                <2>  jmp short $+2
  2129 00001AFC EB00                <2>  jmp short $+2
  3237 00001AFE FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3238 00001AFF B002                <1> 	mov	al, 2			; MODE FOR 8237
  3239 00001B01 E60A                <1> 	OUT	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3240                              <1> 
  3241 00001B03 F8                  <1> 	clc	; 04/02/2016
  3242 00001B04 C3                  <1> 	retn
  3243                              <1> 
  3244                              <1> dma_bnd_err_stc:
  3245 00001B05 F9                  <1> 	stc
  3246                              <1> dma_bnd_err:
  3247 00001B06 C605[CC620000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3248 00001B0D C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3249                              <1> 
  3250                              <1> ;-------------------------------------------------------------------------------
  3251                              <1> ; NEC_INIT	
  3252                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3253                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3254                              <1> ;
  3255                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3256                              <1> ;
  3257                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3258                              <1> ;-------------------------------------------------------------------------------
  3259                              <1> NEC_INIT:
  3260                              <1> 	; 11/07/2022
  3261                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3262                              <1> 	;push	ax			; SAVE NEC COMMAND
  3263                              <1> 	; 24/12/2021
  3264 00001B0E 50                  <1> 	push	eax
  3265 00001B0F E886020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3266                              <1> 
  3267                              <1> ;-----	DO THE SEEK OPERATION
  3268                              <1> 
  3269                              <1> 	;mov	ch, [ebp+1]		; CH = TRACK #
  3270                              <1> 	; 11/07/2022
  3271 00001B14 89F1                <1> 	mov	ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector
  3272 00001B16 C1E908              <1> 	shr	ecx, 8
  3273                              <1> 	; ch = track #	
  3274                              <1> 
  3275 00001B19 E86B030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3276                              <1> 	;pop	ax			; RECOVER COMMAND
  3277                              <1> 	; 24/12/2021
  3278 00001B1E 58                  <1> 	pop	eax
  3279 00001B1F 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3280 00001B21 BB[3E1B0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3281 00001B26 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3282                              <1> 
  3283                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3284                              <1> 
  3285 00001B27 E824030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3286 00001B2C 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3287 00001B2E 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3288 00001B30 C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3289 00001B33 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3290 00001B36 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3291 00001B38 E813030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3292 00001B3D 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3293                              <1> ER_1:
  3294 00001B3E C3                  <1> 	retn
  3295                              <1> 
  3296                              <1> ;-------------------------------------------------------------------------------
  3297                              <1> ; RWV_COM
  3298                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3299                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3300                              <1> ;
  3301                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3302                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3303                              <1> ;-------------------------------------------------------------------------------
  3304                              <1> RWV_COM:
  3305                              <1> 	; 11/07/2022
  3306                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3307 00001B3F B8[8C1B0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3308 00001B44 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3309                              <1> 	;mov	ah, [ebp+1]		; OUTPUT TRACK #
  3310                              <1> 	; 11/07/2022
  3311 00001B45 89F0                <1> 	mov	eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track
  3312 00001B47 C1E808              <1> 	shr	eax, 8
  3313                              <1> 	; ah = track # 
  3314 00001B4A E801030000          <1> 	call	NEC_OUTPUT
  3315 00001B4F 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3316                              <1> 	; ah = head #
  3317 00001B51 E8FA020000          <1> 	call	NEC_OUTPUT
  3318                              <1>         ;mov	ah, [ebp]		; OUTPUT SECTOR #
  3319 00001B56 89F0                <1> 	mov	eax, esi
  3320 00001B58 88C4                <1> 	mov	ah, al
  3321                              <1>  	; ah = sector #
  3322 00001B5A E8F1020000          <1> 	CALL	NEC_OUTPUT
  3323                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3324 00001B5F B003                <1> 	mov	al, 3 ; 08/07/2022
  3325 00001B61 E8F9010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3326 00001B66 E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3327                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3328 00001B6B B004                <1> 	mov	al, 4 ; 08/07/2022
  3329 00001B6D E8ED010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3330 00001B72 E8D9020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3331 00001B77 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3332                              <1> _R15:
  3333 00001B7A E8D1020000          <1> 	call	NEC_OUTPUT
  3334                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3335 00001B7F B006                <1> 	mov	al, 6 ; 08/07/2022
  3336 00001B81 E8D9010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3337 00001B86 E8C5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3338 00001B8B 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3339                              <1> ER_2:
  3340 00001B8C C3                  <1> 	retn
  3341                              <1> 
  3342                              <1> ;-------------------------------------------------------------------------------
  3343                              <1> ; NEC_TERM
  3344                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3345                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3346                              <1> ;
  3347                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3348                              <1> ;-------------------------------------------------------------------------------
  3349                              <1> 
  3350                              <1> NEC_TERM:
  3351                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3352                              <1> 
  3353                              <1> ;-----	LET THE OPERATION HAPPEN
  3354                              <1> 
  3355 00001B8D 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3356 00001B8E E8C7030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3357 00001B93 9C                  <1> 	pushfd	; 24/12/2021
  3358 00001B94 E8F0030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3359 00001B99 724B                <1> 	jc	short SET_END_POP
  3360 00001B9B 9D                  <1> 	popfd	; 24/12/2021
  3361 00001B9C 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3362                              <1> 
  3363                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3364                              <1> 
  3365 00001B9E FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3366 00001B9F BE[CD620000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3367 00001BA4 AC                  <1> 	lodsb				; GET ST0
  3368 00001BA5 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3369 00001BA7 7433                <1> 	jz	short SET_END
  3370 00001BA9 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3371 00001BAB 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3372                              <1> 
  3373                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3374                              <1> 
  3375 00001BAD AC                  <1> 	lodsb				; GET ST1
  3376 00001BAE D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3377 00001BB0 B404                <1> 	mov	ah, RECORD_NOT_FND
  3378 00001BB2 7222                <1> 	jc	short J19
  3379 00001BB4 C0E002              <1> 	sal	al, 2
  3380 00001BB7 B410                <1> 	mov	ah, BAD_CRC
  3381 00001BB9 721B                <1> 	jc	short J19
  3382 00001BBB D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3383 00001BBD B408                <1> 	mov	ah, BAD_DMA
  3384 00001BBF 7215                <1> 	jc	short J19
  3385 00001BC1 C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3386 00001BC4 B404                <1> 	mov	ah, RECORD_NOT_FND
  3387 00001BC6 720E                <1> 	jc	short J19
  3388 00001BC8 D0E0                <1> 	sal	al, 1
  3389 00001BCA B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3390 00001BCC 7208                <1> 	jc	short J19
  3391 00001BCE D0E0                <1> 	sal	al, 1			; TEST MISSING ADDRESS MARK
  3392 00001BD0 B402                <1> 	mov	ah, BAD_ADDR_MARK
  3393 00001BD2 7202                <1> 	jc	short J19
  3394                              <1> 
  3395                              <1> ;----- 	NEC MUST HAVE FAILED
  3396                              <1> J18:
  3397 00001BD4 B420                <1> 	mov	ah, BAD_NEC
  3398                              <1> J19:
  3399 00001BD6 0825[CC620000]      <1> 	or	[DSKETTE_STATUS], ah
  3400                              <1> SET_END:
  3401 00001BDC 803D[CC620000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3402 00001BE3 F5                  <1> 	cmc
  3403 00001BE4 5E                  <1> 	pop	esi
  3404 00001BE5 C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3405                              <1> 
  3406                              <1> SET_END_POP:
  3407 00001BE6 9D                  <1> 	popfd	; 24/12/2021
  3408 00001BE7 EBF3                <1> 	jmp	short SET_END
  3409                              <1> 
  3410                              <1> ;-------------------------------------------------------------------------------
  3411                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3412                              <1> ;-------------------------------------------------------------------------------
  3413                              <1> DSTATE:
  3414                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3415 00001BE9 803D[CC620000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3416 00001BF0 753E                <1> 	jne	short SETBAC		; IF ERROR JUMP
  3417 00001BF2 808F[D7620000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3418 00001BF9 F687[D7620000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3419 00001C00 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3420 00001C02 8A87[D7620000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3421 00001C08 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3422 00001C0A 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3423 00001C0C 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3424                              <1> 
  3425                              <1> ;----- 	CHECK IF IT IS 1.44M
  3426                              <1> 
  3427 00001C0E E843010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3428                              <1> 	;;20/02/2015
  3429                              <1> 	;;jc	short M_12		; CMOS BAD
  3430 00001C13 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3431 00001C15 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3432 00001C17 7410                <1> 	je	short M_12		; YES
  3433                              <1> M_720:
  3434 00001C19 80A7[D7620000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3435 00001C20 808F[D7620000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3436 00001C27 EB07                <1> 	jmp	short SETBAC		; BACK
  3437                              <1> M_12:	
  3438 00001C29 808F[D7620000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3439                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3440                              <1> SETBAC:
  3441 00001C30 C3                  <1> 	retn
  3442                              <1> 
  3443                              <1> ;-------------------------------------------------------------------------------
  3444                              <1> ; RETRY	
  3445                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3446                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3447                              <1> ;
  3448                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3449                              <1> ;-------------------------------------------------------------------------------
  3450                              <1> RETRY:
  3451                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3452 00001C31 803D[CC620000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3453 00001C38 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3454 00001C3A 803D[CC620000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3455 00001C41 743B                <1> 	je	short NO_RETRY
  3456 00001C43 8AA7[D7620000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3457 00001C49 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3458 00001C4C 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3459 00001C4E 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3460 00001C51 8A2D[D4620000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3461 00001C57 C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3462 00001C5A 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3463 00001C5D 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3464 00001C5F 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3465                              <1> 
  3466                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3467                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3468                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3469                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3470                              <1> 
  3471 00001C61 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3472 00001C64 D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3473 00001C66 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3474 00001C69 80A7[D7620000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3475                              <1> 					; RATE, DBL STEP OFF
  3476 00001C70 08A7[D7620000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3477 00001C76 C605[CC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3478 00001C7D F9                  <1> 	stc				; SET CARRY FOR RETRY
  3479                              <1> NO_RETRY:	; 08/07/2022
  3480 00001C7E C3                  <1> 	retn				; RETRY RETURN
  3481                              <1> 
  3482                              <1> ;NO_RETRY:
  3483                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3484                              <1> 	;RETn				; NO RETRY RETURN
  3485                              <1> 
  3486                              <1> ;-------------------------------------------------------------------------------
  3487                              <1> ; NUM_TRANS
  3488                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3489                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3490                              <1> ;
  3491                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3492                              <1> ;		SI-HI  = HEAD
  3493                              <1> ;		[BP]   = START SECTOR
  3494                              <1> ;
  3495                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3496                              <1> ;-------------------------------------------------------------------------------
  3497                              <1> NUM_TRANS:
  3498                              <1> 	; 11/07/2022
  3499                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3500 00001C7F 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3501 00001C81 803D[CC620000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3502                              <1> 	; 24/12/2021
  3503 00001C88 7529                <1> 	jne	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3504                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3505 00001C8A B004                <1> 	mov	al, 4 ; 08/07/2022
  3506 00001C8C E8CE000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3507                              <1> 	;mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3508 00001C91 A0[D2620000]        <1> 	mov	al, [NEC_STATUS+5]
  3509 00001C96 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3510 00001C98 88CB                <1> 	mov	bl, cl ; 11/07/2022 ; sector #
  3511 00001C9A 3A2D[D1620000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3512 00001CA0 750D                <1> 	jne	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3513                              <1> 	; 11/07/2022
  3514                              <1> 	;mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3515                              <1> 	;cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3516                              <1> 	;jz	short SAME_TR		; IF SAME TRACK NO INCREASE
  3517 00001CA2 C1E908              <1> 	shr	ecx, 8 ; byte 3 = track # --> byte 2
  3518 00001CA5 3A2D[D0620000]      <1> 	cmp	ch, [NEC_STATUS+3]
  3519 00001CAB 7404                <1> 	je	short SAME_TRK		
  3520                              <1> 	; 11/07/2022
  3521                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3522 00001CAD 00E0                <1> 	add	al, ah
  3523                              <1> DIF_HD:
  3524                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3525 00001CAF 00E0                <1> 	add	al, ah
  3526                              <1> SAME_TRK:
  3527                              <1> 	;sub	bl, [ebp]		; SUBTRACT START FROM END
  3528                              <1> 	;mov	al, bl			; TO AL
  3529 00001CB1 28D8                <1> 	sub	al, bl
  3530                              <1> NT_OUT:
  3531 00001CB3 C3                  <1> 	retn
  3532                              <1> 
  3533                              <1> ;-------------------------------------------------------------------------------
  3534                              <1> ; SETUP_DBL
  3535                              <1> ;	CHECK DOUBLE STEP.
  3536                              <1> ;
  3537                              <1> ; ON ENTRY :	EDI = DRIVE #
  3538                              <1> ;
  3539                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3540                              <1> ;-------------------------------------------------------------------------------
  3541                              <1> SETUP_DBL:
  3542                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3543 00001CB4 8AA7[D7620000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3544 00001CBA F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3545 00001CBD 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3546                              <1> 
  3547                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3548                              <1> 
  3549 00001CBF C605[C9620000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3550 00001CC6 E8CF000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3551 00001CCB B500                <1> 	mov	ch, 0			; LOAD TRACK 0
  3552 00001CCD E8B7010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3553 00001CD2 E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3554 00001CD7 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3555                              <1> 
  3556                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3557                              <1> 
  3558 00001CD9 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3559 00001CDD F687[D7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3560 00001CE4 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3561 00001CE6 B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3562                              <1> 
  3563                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3564                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3565                              <1> ;	THEN SET DOUBLE STEP ON.
  3566                              <1> 
  3567                              <1> CNT_OK:
  3568 00001CE8 C605[CB620000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3569                              <1> 	; 24/12/2021
  3570 00001CEF 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3571 00001CF0 C605[CC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3572 00001CF7 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3573 00001CF9 D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3574 00001CFB C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3575                              <1> 	; 24/12/2021
  3576 00001CFE 50                  <1> 	push	eax			; SAVE HEAD
  3577 00001CFF E885010000          <1> 	call	SEEK			; SEEK TO TRACK
  3578                              <1> 	; 24/12/2021
  3579 00001D04 58                  <1> 	pop	eax			; RESTORE HEAD
  3580 00001D05 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3581 00001D07 E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3582 00001D0C 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3583 00001D0D 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3584 00001D12 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3585                              <1> 	; 24/12/2021
  3586 00001D13 59                  <1> 	pop	ecx			; RESTORE COUNT
  3587 00001D14 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3588 00001D16 FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3589 00001D18 38CD                <1> 	cmp	ch, cl			; REACHED MAXIMUM YET
  3590 00001D1A 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3591                              <1> 
  3592                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3593                              <1> 
  3594                              <1> SD_ERR:	
  3595 00001D1C F9                  <1> 	stc				; SET CARRY FOR ERROR
  3596 00001D1D C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3597                              <1> 
  3598                              <1> DO_CHK:
  3599 00001D1E 8A0D[D0620000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3600 00001D24 888F[D9620000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3601 00001D2A D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3602 00001D2C 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3603 00001D2E 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3604 00001D30 808F[D7620000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3605                              <1> NO_DBL:
  3606 00001D37 F8                  <1> 	clc				; CLEAR ERROR FLAG
  3607 00001D38 C3                  <1> 	retn
  3608                              <1> 
  3609                              <1> ;-------------------------------------------------------------------------------
  3610                              <1> ; READ_ID
  3611                              <1> ;	READ ID FUNCTION.
  3612                              <1> ;
  3613                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3614                              <1> ;
  3615                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3616                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3617                              <1> ;-------------------------------------------------------------------------------
  3618                              <1> READ_ID:
  3619                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3620 00001D39 B8[551D0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3621 00001D3E 50                  <1> 	push	eax
  3622 00001D3F B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3623 00001D41 E80A010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3624 00001D46 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3625 00001D48 88C4                <1> 	mov	ah, al
  3626 00001D4A E801010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3627 00001D4F E839FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3628 00001D54 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3629                              <1> ER_3:
  3630 00001D55 C3                  <1> 	retn
  3631                              <1> 
  3632                              <1> ;-------------------------------------------------------------------------------
  3633                              <1> ; CMOS_TYPE
  3634                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3635                              <1> ;
  3636                              <1> ; ON ENTRY:	EDI = DRIVE #
  3637                              <1> ;
  3638                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3639                              <1> ;-------------------------------------------------------------------------------
  3640                              <1> 
  3641                              <1> CMOS_TYPE: ; 11/12/2014
  3642                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3643 00001D56 8A87[6C5D0000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3644 00001D5C 20C0                <1> 	and 	al, al ; 18/12/2014
  3645 00001D5E C3                  <1> 	retn
  3646                              <1> 
  3647                              <1> ;-------------------------------------------------------------------------------
  3648                              <1> ; GET_PARM
  3649                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3650                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3651                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3652                              <1> ;	THE PARAMETER IN DL.
  3653                              <1> ;
  3654                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3655                              <1> ;
  3656                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3657                              <1> ;		AL DESTROYED
  3658                              <1> ;-------------------------------------------------------------------------------
  3659                              <1> GET_PARM:
  3660                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3661                              <1> 	;	 ENTRY:
  3662                              <1> 	;	     AL = INDEX
  3663                              <1> 	;	    EDI = DRIVE #
  3664                              <1> 	; 	 RETURN:
  3665                              <1> 	;	     AH = REQUESTED PARAMETER
  3666                              <1> 	;	     AL DESTROYED
  3667                              <1> 	
  3668                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3669                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3670                              <1> 	;push	esi ; 11/07/2022
  3671 00001D5F 53                  <1> 	push	ebx			; SAVE EBX	
  3672 00001D60 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3673                              <1>    	; 17/12/2014
  3674                              <1> 	;mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3675                              <1> 	; 11/07/2022
  3676                              <1> 	;cmp	al, ah
  3677                              <1> 	;je	short gpndc
  3678                              <1> 
  3679                              <1> 	; 11/07/2022
  3680 00001D63 89F8                <1> 	mov	eax, edi
  3681 00001D65 3A05[615D0000]      <1> 	cmp	al, [pfd] ; is same with previous drive # ?
  3682 00001D6B 7423                <1> 	je	short gpndc	
  3683                              <1> 
  3684 00001D6D A2[615D0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3685                              <1> 
  3686 00001D72 53                  <1> 	push	ebx ; 08/02/2015
  3687                              <1> 	
  3688                              <1> 	;mov	bl, al 
  3689                              <1> 	; 11/12/2014
  3690                              <1> 	;mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3691                              <1> 	; 11/07/2022
  3692 00001D73 8A87[6C5D0000]      <1> 	mov	al, [edi+fd0_type]	; Drive type (0,1,2,3,4)	
  3693                              <1> 	; 18/12/2014
  3694 00001D79 20C0                <1> 	and	al, al
  3695 00001D7B 7507                <1> 	jnz	short gpdtc
  3696 00001D7D BB[4B5D0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3697 00001D82 EB05                <1>         jmp     short gpdpu
  3698                              <1> gpdtc:	
  3699 00001D84 E89BFBFFFF          <1> 	call	DR_TYPE_CHECK
  3700                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3701                              <1> gpdpu:
  3702 00001D89 891D[E85C0000]      <1> 	mov	[DISK_POINTER], ebx
  3703 00001D8F 5B                  <1> 	pop	ebx
  3704                              <1> gpndc:
  3705                              <1> 	;mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3706                              <1> 	;mov	ah, [esi+ebx]		; GET THE WORD
  3707                              <1> 	; 11/07/2022
  3708 00001D90 031D[E85C0000]      <1> 	add	ebx, [DISK_POINTER]
  3709 00001D96 8A23                <1> 	mov	ah, [ebx] 
  3710 00001D98 5B                  <1> 	pop	ebx			; RESTORE EBX
  3711                              <1> 	;pop	esi ; 11/07/2022
  3712 00001D99 C3                  <1> 	retn
  3713                              <1> 
  3714                              <1> ;-------------------------------------------------------------------------------
  3715                              <1> ; MOTOR_ON
  3716                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3717                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3718                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3719                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3720                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3721                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3722                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3723                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3724                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3725                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3726                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3727                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3728                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3729                              <1> ;
  3730                              <1> ; ON ENTRY:	EDI = DRIVE #
  3731                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3732                              <1> ;-------------------------------------------------------------------------------
  3733                              <1> MOTOR_ON:
  3734                              <1> 	; 12/07/2022
  3735                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3736 00001D9A 53                  <1> 	push	ebx			; SAVE REG.
  3737 00001D9B E820000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3738 00001DA0 721C                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3739                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3740                              <1> 	; 08/07/2022
  3741                              <1> 	;call	XLAT_NEW ; 12/07/2022	; TRANSLATE STATE TO PRESENT ARCH,
  3742                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3743                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3744                              <1> M_WAIT:
  3745                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3746 00001DA2 B00A                <1> 	mov	al, 10 ; 08/07/2022
  3747 00001DA4 E8B6FFFFFF          <1> 	call	GET_PARM
  3748                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3749 00001DA9 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3750                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3751 00001DAC 7302                <1> 	jae	short J13
  3752 00001DAE B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3753                              <1> 
  3754                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3755                              <1> GP2:	
  3756                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3757                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3758 00001DB0 B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3759 00001DB5 E8F9F6FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3760                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3761 00001DBA FECC                <1> 	dec	ah
  3762 00001DBC 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3763                              <1> MOT_IS_ON:
  3764 00001DBE 5B                  <1> 	pop	ebx			; RESTORE REG.
  3765 00001DBF C3                  <1> 	retn
  3766                              <1> 
  3767                              <1> ;-------------------------------------------------------------------------------
  3768                              <1> ; TURN_ON
  3769                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3770                              <1> ;
  3771                              <1> ; ON ENTRY:	EDI = DRIVE #
  3772                              <1> ;
  3773                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3774                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3775                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3776                              <1> ;-------------------------------------------------------------------------------
  3777                              <1> TURN_ON:
  3778                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3779 00001DC0 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3780 00001DC2 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3781 00001DC4 C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3782 00001DC7 FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3783 00001DC8 C605[CB620000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3784 00001DCF A0[CA620000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3785 00001DD4 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3786 00001DD6 B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3787 00001DD8 D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3788                              <1> 
  3789                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3790                              <1> ;  BL = DRIVE SELECT DESIRED
  3791                              <1> ;  AH = MOTOR ON MASK DESIRED
  3792                              <1> 
  3793 00001DDA 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3794 00001DDC 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3795 00001DDE 8425[CA620000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3796 00001DE4 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3797                              <1> 
  3798                              <1> TURN_IT_ON:
  3799 00001DE6 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3800 00001DE8 8A3D[CA620000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3801 00001DEE 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3802 00001DF1 8025[CA620000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3803 00001DF8 0825[CA620000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3804 00001DFE A0[CA620000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3805 00001E03 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3806 00001E05 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3807 00001E08 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3808 00001E09 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3809 00001E0B C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3810 00001E0E 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3811 00001E10 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3812 00001E14 EE                  <1> 	out	dx, al
  3813 00001E15 38FB                <1> 	cmp	bl, bh			; NEW MOTOR TURNED ON ?
  3814                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3815 00001E17 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3816 00001E19 F8                  <1> 	clc				; RESET CARRY MEANING WAIT
  3817 00001E1A C3                  <1> 	retn
  3818                              <1> 
  3819                              <1> NO_MOT_WAIT:
  3820 00001E1B FB                  <1> 	sti
  3821                              <1> no_mot_w1: ; 27/02/2015
  3822 00001E1C F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3823                              <1> 	;sti				; INTERRUPTS BACK ON
  3824 00001E1D C3                  <1> 	retn
  3825                              <1> 
  3826                              <1> ;-------------------------------------------------------------------------------
  3827                              <1> ; HD_WAIT
  3828                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3829                              <1> ;
  3830                              <1> ; ON ENTRY:	DI = DRIVE #
  3831                              <1> ;
  3832                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  3833                              <1> ;-------------------------------------------------------------------------------
  3834                              <1> HD_WAIT:
  3835                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3836                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3837 00001E1E B009                <1> 	mov	al, 9	; 08/07/2022
  3838 00001E20 E83AFFFFFF          <1> 	CALL	GET_PARM
  3839 00001E25 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3840 00001E27 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3841 00001E29 F605[CA620000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3842                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3843                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3844                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3845 00001E30 741D                <1> 	jz	short HW_DONE
  3846 00001E32 B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3847 00001E34 8A87[D7620000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3848 00001E3A 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3849 00001E3C 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3850 00001E3E 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3851                              <1> ;GP3:
  3852 00001E40 B414                <1> 	mov	ah, HD320_SETTLE		; USE 320/360 HEAD SETTLE
  3853                              <1> ;	jmp	short DO_WAT
  3854                              <1> 
  3855                              <1> ;ISNT_WRITE:
  3856                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3857                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3858                              <1> 
  3859                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3860                              <1> DO_WAT:
  3861                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3862                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3863                              <1> J29:					; 	1 MILLISECOND LOOP
  3864                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3865                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3866                              <1> 	; 08/07/2022
  3867 00001E42 29C9                <1> 	sub	ecx, ecx
  3868 00001E44 B142                <1> 	mov	cl, 66
  3869 00001E46 E868F6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3870                              <1> 	;dec	al			; DECREMENT THE COUNT
  3871 00001E4B FECC                <1> 	dec	ah
  3872 00001E4D 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3873                              <1> HW_DONE:
  3874 00001E4F C3                  <1> 	retn
  3875                              <1> 
  3876                              <1> ;-------------------------------------------------------------------------------
  3877                              <1> ; NEC_OUTPUT
  3878                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3879                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3880                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3881                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3882                              <1> ; 
  3883                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3884                              <1> ;
  3885                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3886                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3887                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3888                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3889                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3890                              <1> ;
  3891                              <1> ;		EAX, ECX, EDX DESTROYED
  3892                              <1> ;-------------------------------------------------------------------------------
  3893                              <1> 
  3894                              <1> ; 09/12/2014 [Erdogan Tan] 
  3895                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3896                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3897                              <1> ;	This read only register facilitates the transfer of data between
  3898                              <1> ;	the system microprocessor and the controller.
  3899                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3900                              <1> ;	  with the system micrprocessor.
  3901                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3902                              <1> ;	  the transfer is to the controller.
  3903                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3904                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3905                              <1> ; Bit 3 - Reserved.
  3906                              <1> ; Bit 2 - Reserved.
  3907                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3908                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3909                              <1> 
  3910                              <1> ; Data Register (3F5h)
  3911                              <1> ; This read/write register passes data, commands and parameters, and provides
  3912                              <1> ; diskette status information.
  3913                              <1>   		
  3914                              <1> NEC_OUTPUT:
  3915                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3916                              <1> 	;push	ebx			; SAVE REG.
  3917 00001E50 BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  3918                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  3919                              <1> 	; 16/12/2014
  3920                              <1> 	; waiting for (max.) 0.5 seconds
  3921                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  3922                              <1> 	;
  3923                              <1> 	; 17/12/2014
  3924                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  3925                              <1> 	;
  3926                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  3927                              <1> 	;		go on.
  3928                              <1> 	;INPUT:
  3929                              <1> 	;	AH=Mask for isolation bits.
  3930                              <1> 	;	AL=pattern to look for.
  3931                              <1> 	;	DX=Port to test for
  3932                              <1> 	;	ECX=Number of memory refresh periods to delay.
  3933                              <1> 	;	     (normally 30 microseconds per period.)
  3934                              <1> 	;
  3935                              <1> 	;WFP_SHORT:  
  3936                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  3937                              <1> 	;
  3938                              <1> 
  3939 00001E55 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  3940                              <1> ;
  3941                              <1> ;WFPS_OUTER_LP:
  3942                              <1> ;	;
  3943                              <1> ;WFPS_CHECK_PORT:
  3944                              <1> J23:
  3945 00001E5A EC                  <1> 	in	al, dx			; GET STATUS
  3946 00001E5B 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  3947 00001E5D 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  3948 00001E5F 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  3949                              <1> WFPS_HI:
  3950 00001E61 E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  3951 00001E63 A810                <1> 	test	al, 010h		; transition on memory
  3952 00001E65 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  3953                              <1> WFPS_LO:
  3954 00001E67 E461                <1> 	in	al, PORT_B		; SYS1
  3955 00001E69 A810                <1> 	test	al, 010h
  3956 00001E6B 74FA                <1> 	jz	short WFPS_LO
  3957                              <1> 	;loop	short WFPS_CHECK_PORT
  3958 00001E6D E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  3959                              <1> 
  3960                              <1> 	; fail
  3961                              <1> 
  3962                              <1> ;WFPS_TIMEOUT:
  3963                              <1> 
  3964                              <1> ;-----	FALL THRU TO ERROR RETURN
  3965                              <1> 
  3966 00001E6F 800D[CC620000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  3967                              <1> 	;pop	ebx			; RESTORE REG.
  3968 00001E76 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  3969 00001E77 F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  3970 00001E78 C3                  <1> 	retn
  3971                              <1> 
  3972                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  3973                              <1> 
  3974                              <1> J27:	
  3975 00001E79 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  3976 00001E7B 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  3977 00001E7C EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  3978                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  3979                              <1> 	; 27/02/2015
  3980 00001E7D 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  3981                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  3982 00001E7E 29C9                <1> 	sub	ecx, ecx
  3983 00001E80 B103                <1> 	mov	cl, 3 ; 24/12/2021
  3984 00001E82 E82CF6FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  3985 00001E87 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  3986                              <1> 	;pop	ebx			; RESTORE REG
  3987 00001E88 C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  3988                              <1> 
  3989                              <1> ;-------------------------------------------------------------------------------
  3990                              <1> ; SEEK
  3991                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  3992                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  3993                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  3994                              <1> ;
  3995                              <1> ; ON ENTRY:	EDI = DRIVE #
  3996                              <1> ;		CH = TRACK #
  3997                              <1> ;
  3998                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  3999                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4000                              <1> ;-------------------------------------------------------------------------------
  4001                              <1> SEEK:
  4002                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4003 00001E89 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4004 00001E8B B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4005 00001E8D 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  4006 00001E8F D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  4007 00001E91 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  4008 00001E93 8405[C9620000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4009 00001E99 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4010                              <1> 
  4011 00001E9B 0805[C9620000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4012 00001EA1 E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4013 00001EA6 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  4014                              <1> 
  4015                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4016                              <1> 
  4017 00001EA8 C605[CC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  4018 00001EAF E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4019 00001EB4 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4020                              <1> 
  4021                              <1> AFT_RECAL:
  4022 00001EB6 C687[D9620000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  4023 00001EBD 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  4024 00001EBF 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4025                              <1> 
  4026                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4027                              <1> 
  4028 00001EC1 F687[D7620000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4029 00001EC8 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4030 00001ECA D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  4031                              <1> 
  4032 00001ECC 3AAF[D9620000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  4033 00001ED2 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  4034                              <1> 
  4035 00001ED4 BA[071F0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  4036 00001ED9 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4037 00001EDA 88AF[D9620000]      <1> 	mov	[DSK_TRK+edi], ch	; SAVE NEW CYLINDER AS PRESENT POSITION
  4038 00001EE0 B40F                <1> 	mov	ah, 0Fh			; SEEK COMMAND TO NEC
  4039 00001EE2 E869FFFFFF          <1> 	call	NEC_OUTPUT
  4040 00001EE7 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4041 00001EE9 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  4042 00001EEB E860FFFFFF          <1> 	call	NEC_OUTPUT
  4043 00001EF0 8AA7[D9620000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  4044 00001EF6 E855FFFFFF          <1> 	call	NEC_OUTPUT
  4045 00001EFB E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4046                              <1> 
  4047                              <1> ;-----	WAIT FOR HEAD SETTLE
  4048                              <1> 
  4049                              <1> DO_WAIT:
  4050 00001F00 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  4051 00001F01 E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4052 00001F06 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  4053                              <1> RB:
  4054                              <1> NEC_ERR:
  4055                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4056                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4057 00001F07 C3                  <1> 	retn				; RETURN TO CALLER
  4058                              <1> 
  4059                              <1> ;-------------------------------------------------------------------------------
  4060                              <1> ; RECAL
  4061                              <1> ;	RECALIBRATE DRIVE
  4062                              <1> ;
  4063                              <1> ; ON ENTRY:	EDI = DRIVE #
  4064                              <1> ;
  4065                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4066                              <1> ;-------------------------------------------------------------------------------
  4067                              <1> RECAL:
  4068                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4069                              <1> 	;push	cx
  4070                              <1> 	; 24/12/2021
  4071 00001F08 51                  <1> 	push	ecx
  4072 00001F09 B8[251F0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4073 00001F0E 50                  <1> 	push	eax
  4074 00001F0F B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4075 00001F11 E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4076 00001F16 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4077 00001F18 88DC                <1> 	mov	ah, bl
  4078 00001F1A E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4079 00001F1F E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4080 00001F24 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4081                              <1> RC_BACK:
  4082                              <1> 	;pop	cx
  4083                              <1> 	; 24/12/2021
  4084 00001F25 59                  <1> 	pop	ecx
  4085 00001F26 C3                  <1> 	RETn
  4086                              <1> 
  4087                              <1> ;-------------------------------------------------------------------------------
  4088                              <1> ; CHK_STAT_2
  4089                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4090                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4091                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4092                              <1> ;
  4093                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4094                              <1> ;-------------------------------------------------------------------------------
  4095                              <1> CHK_STAT_2:
  4096                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4097 00001F27 B8[4F1F0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4098 00001F2C 50                  <1> 	push	eax
  4099 00001F2D E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4100 00001F32 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4101 00001F34 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4102 00001F36 E815FFFFFF          <1> 	call	NEC_OUTPUT
  4103 00001F3B E849000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4104 00001F40 720C                <1> 	jc	short J34
  4105 00001F42 A0[CD620000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4106 00001F47 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4107 00001F49 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4108 00001F4B 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4109 00001F4D F8                  <1> 	clc				; GOOD RETURN
  4110                              <1> J34:
  4111 00001F4E 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4112                              <1> CS_BACK:
  4113 00001F4F C3                  <1> 	retn
  4114                              <1> J35:
  4115 00001F50 800D[CC620000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4116 00001F57 F9                  <1> 	stc				; ERROR RETURN CODE
  4117 00001F58 EBF4                <1> 	jmp	short J34
  4118                              <1> 
  4119                              <1> ;-------------------------------------------------------------------------------
  4120                              <1> ; WAIT_INT
  4121                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4122                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4123                              <1> ;	IF THE DRIVE IS NOT READY.
  4124                              <1> ;
  4125                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4126                              <1> ;-------------------------------------------------------------------------------
  4127                              <1> 
  4128                              <1> ; 17/12/2014
  4129                              <1> ; 2.5 seconds waiting !
  4130                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4131                              <1> ; amount of time to wait for completion interrupt from NEC.
  4132                              <1> 
  4133                              <1> WAIT_INT:
  4134                              <1> 	; 12/07/2022
  4135                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4136 00001F5A FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4137                              <1> 	; 12/07/2022
  4138                              <1> 	;clc				; CLEAR TIMEOUT INDICATOR
  4139                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4140                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4141                              <1> 
  4142                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4143                              <1> 	;
  4144                              <1> 	;WAIT_FOR_MEM:	
  4145                              <1> 	;	Waits for a bit at a specified memory location pointed
  4146                              <1> 	;	to by ES:[DI] to become set.
  4147                              <1> 	;INPUT:
  4148                              <1> 	;	AH=Mask to test with.
  4149                              <1> 	;	ES:[DI] = memory location to watch.
  4150                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4151                              <1> 	;	     (normally 30 microseconds per period.)
  4152                              <1> 
  4153                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4154                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4155                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4156                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4157                              <1> 	; 27/02/2015
  4158 00001F5B B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4159                              <1> WFMS_CHECK_MEM:
  4160 00001F60 F605[C9620000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4161 00001F67 7516                <1>         jnz     short J37
  4162                              <1> WFMS_HI:
  4163 00001F69 E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4164 00001F6B A810                <1> 	test	al, 010h		; transition on memory
  4165 00001F6D 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4166                              <1> WFMS_LO:
  4167 00001F6F E461                <1> 	in	al, PORT_B		; SYS1
  4168 00001F71 A810                <1> 	test	al, 010h
  4169 00001F73 74FA                <1> 	jz	short WFMS_LO
  4170 00001F75 E2E9                <1>         loop	WFMS_CHECK_MEM
  4171                              <1> ;WFMS_OUTER_LP:
  4172                              <1> ;;	or	bl, bl			; check outer counter
  4173                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4174                              <1> ;	dec	bl
  4175                              <1> ;	jz	short J36A	
  4176                              <1> ;	jmp	short WFMS_CHECK_MEM
  4177                              <1> 
  4178                              <1> 	;17/12/2014
  4179                              <1> 	;16/12/2014
  4180                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4181                              <1> ;J36:
  4182                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4183                              <1> ;	jnz	short J37
  4184                              <1> 	;16/12/2014
  4185                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4186                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4187                              <1> 	;jnz	short J36
  4188                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4189                              <1> ;	jb	short J36
  4190                              <1> 
  4191                              <1> ;WFMS_TIMEOUT:
  4192                              <1> ;J36A:
  4193 00001F77 800D[CC620000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4194 00001F7E F9                  <1> 	stc				; ERROR RETURN
  4195                              <1> J37:
  4196 00001F7F 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4197 00001F80 8025[C9620000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4198 00001F87 9D                  <1> 	popf				; RECOVER CARRY
  4199 00001F88 C3                  <1> 	retn				; GOOD RETURN CODE
  4200                              <1> 
  4201                              <1> ;-------------------------------------------------------------------------------
  4202                              <1> ; RESULTS
  4203                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4204                              <1> ;	FOLLOWING AN INTERRUPT.
  4205                              <1> ;
  4206                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4207                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4208                              <1> ;-------------------------------------------------------------------------------
  4209                              <1> RESULTS:
  4210                              <1> 	; 12/07/2022
  4211                              <1> 	; 11/07/2022
  4212                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4213 00001F89 57                  <1> 	push	edi
  4214 00001F8A BF[CD620000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4215 00001F8F B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4216 00001F91 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4217                              <1> 
  4218                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4219                              <1> 
  4220                              <1> _R10: 
  4221                              <1> 	; 16/12/2014
  4222                              <1> 	; wait for (max) 0.5 seconds
  4223                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4224                              <1> 	;xor	cx, cx			; COUNTER
  4225                              <1> 
  4226                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4227                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4228                              <1> 	; 27/02/2015
  4229                              <1> 
  4230 00001F95 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4231                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4232                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4233                              <1> 
  4234                              <1> WFPSR_OUTER_LP:
  4235                              <1> 	;
  4236                              <1> WFPSR_CHECK_PORT:
  4237                              <1> J39:					; WAIT FOR MASTER
  4238 00001F9A EC                  <1> 	in	al, dx			; GET STATUS
  4239 00001F9B 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4240 00001F9D 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4241 00001F9F 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4242                              <1> WFPSR_HI:
  4243 00001FA1 E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4244 00001FA3 A810                <1> 	test	al, 010h		; transition on memory
  4245 00001FA5 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4246                              <1> WFPSR_LO:
  4247 00001FA7 E461                <1> 	in	al, PORT_B		; SYS1
  4248 00001FA9 A810                <1> 	test	al, 010h
  4249 00001FAB 74FA                <1> 	jz	short WFPSR_LO
  4250 00001FAD E2EB                <1>         loop	WFPSR_CHECK_PORT
  4251                              <1> 	
  4252                              <1> 	;; 27/02/2015
  4253                              <1> 	;;dec	bh
  4254                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4255                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4256                              <1> 
  4257                              <1> 	;;mov	byte [wait_count], 0
  4258                              <1> ;J39:					; WAIT FOR MASTER
  4259                              <1> ;	in	al, dx			; GET STATUS
  4260                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4261                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4262                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4263                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4264                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4265                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4266                              <1> 	;
  4267                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4268                              <1> 	;;jb	short J39	
  4269                              <1> 
  4270                              <1> ;WFPSR_TIMEOUT:
  4271 00001FAF 800D[CC620000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4272 00001FB6 F9                  <1> 	stc				; SET ERROR RETURN
  4273 00001FB7 EB26                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4274                              <1> 
  4275                              <1> ;-----	READ IN THE STATUS
  4276                              <1> 
  4277                              <1> J42:
  4278 00001FB9 EB00                <1> 	JMP	$+2			; I/O DELAY
  4279                              <1> 	;inc	dx			; POINT AT DATA PORT
  4280 00001FBB FEC2                <1> 	inc	dl
  4281 00001FBD EC                  <1> 	in	al, dx			; GET THE DATA
  4282                              <1> 	; 16/12/2014
  4283                              <1> 	NEWIODELAY
  2133 00001FBE E6EB                <2>  out 0EBh,al
  4284                              <1> 	
  4285                              <1> 	;mov	[edi], al		; STORE THE BYTE
  4286                              <1> 	;inc	edi			; INCREMENT THE POINTER
  4287                              <1> 	; 11/07/2022
  4288 00001FC0 AA                  <1> 	stosb
  4289                              <1> 
  4290                              <1> 	; 16/12/2014
  4291                              <1> ;	push	cx
  4292                              <1> ;	mov	cx, 30
  4293                              <1> ;wdw2:
  4294                              <1> ;	NEWIODELAY
  4295                              <1> ;	loop	wdw2
  4296                              <1> ;	pop	cx
  4297                              <1> 
  4298                              <1> 	;mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4299                              <1> 	; 12/07/2022
  4300 00001FC1 29C9                <1> 	sub	ecx, ecx
  4301 00001FC3 B103                <1> 	mov	cl, 3
  4302 00001FC5 E8E9F4FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4303                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4304 00001FCA FECA                <1> 	dec	dl
  4305 00001FCC EC                  <1> 	in	al, dx			; GET STATUS
  4306                              <1> 	; 16/12/2014
  4307                              <1> 	NEWIODELAY
  2133 00001FCD E6EB                <2>  out 0EBh,al
  4308                              <1> 	;
  4309 00001FCF A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4310 00001FD1 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4311                              <1> 
  4312 00001FD3 FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4313 00001FD5 75BE                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4314 00001FD7 800D[CC620000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4315 00001FDE F9                  <1> 	stc				; SET ERROR FLAG
  4316                              <1> 
  4317                              <1> ;-----	RESULT OPERATION IS DONE
  4318                              <1> POPRES:
  4319 00001FDF 5F                  <1> 	pop	edi
  4320 00001FE0 C3                  <1> 	retn				; RETURN WITH CARRY SET
  4321                              <1> 
  4322                              <1> ;-------------------------------------------------------------------------------
  4323                              <1> ; READ_DSKCHNG
  4324                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4325                              <1> ;
  4326                              <1> ; ON ENTRY:	EDI = DRIVE #
  4327                              <1> ;
  4328                              <1> ; ON EXIT:	EDI = DRIVE #
  4329                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4330                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4331                              <1> ;		EAX, ECX, EDX DESTROYED
  4332                              <1> ;-------------------------------------------------------------------------------
  4333                              <1> READ_DSKCHNG:
  4334                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4335 00001FE1 E8B4FDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4336 00001FE6 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4337 00001FEA EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4338 00001FEB A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4339 00001FED C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4340                              <1> 
  4341                              <1> fdc_int:  
  4342                              <1> 	  ; 30/07/2015	
  4343                              <1> 	  ; 16/02/2015
  4344                              <1> ;int_0Eh: ; 11/12/2014
  4345                              <1> 
  4346                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  4347                              <1> ; DISK_INT
  4348                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4349                              <1> ;
  4350                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4351                              <1> ;-------------------------------------------------------------------------------
  4352                              <1> DISK_INT_1:
  4353                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4354                              <1> 	;push	eax			; SAVE WORK REGISTER
  4355                              <1> 	; 24/12/2021
  4356 00001FEE 50                  <1> 	push	eax
  4357 00001FEF 1E                  <1> 	push	ds
  4358 00001FF0 66B81000            <1> 	mov	ax, KDATA
  4359 00001FF4 8ED8                <1> 	mov 	ds, ax
  4360 00001FF6 800D[C9620000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4361 00001FFD B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4362 00001FFF E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4363 00002001 1F                  <1> 	pop	ds
  4364                              <1> 	;pop	ax			; RECOVER REGISTER
  4365                              <1> 	; 24/12/2021
  4366 00002002 58                  <1> 	pop	eax
  4367 00002003 CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4368                              <1> 
  4369                              <1> ;-------------------------------------------------------------------------------
  4370                              <1> ; DSKETTE_SETUP
  4371                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4372                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4373                              <1> ;-------------------------------------------------------------------------------
  4374                              <1> DSKETTE_SETUP:
  4375                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4376                              <1> 	;push	eax			; SAVE REGISTERS
  4377                              <1> 	;push	ebx
  4378                              <1> 	;push	ecx
  4379 00002004 52                  <1> 	push	edx
  4380                              <1> 	;push	edi
  4381                              <1> 	; 14/12/2014
  4382                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4383                              <1> 	;
  4384                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4385                              <1> 
  4386 00002005 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4387 00002007 29C9                <1> 	sub	ecx, ecx
  4388 00002009 66890D[D7620000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4389                              <1> 	; 08/07/2022
  4390                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4391 00002010 800D[D4620000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4392 00002017 880D[C9620000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4393 0000201D 880D[CB620000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4394 00002023 880D[CA620000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4395 00002029 880D[CC620000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4396                              <1> 	;
  4397                              <1> 	; 28/02/2015
  4398                              <1> 	;mov	word [cfd], 100h 
  4399 0000202F E87DF8FFFF          <1> 	call	DSK_RESET
  4400 00002034 5A                  <1> 	pop	edx
  4401 00002035 C3                  <1> 	retn
  4402                              <1> 
  4403                              <1> ;//////////////////////////////////////////////////////
  4404                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4405                              <1> ;
  4406                              <1> 
  4407                              <1> ; 12/07/2022
  4408                              <1> ;int13h: ; 21/02/2015
  4409                              <1> ;	pushfd
  4410                              <1> ;	push 	cs
  4411                              <1> ;	call 	DISK_IO
  4412                              <1> ;	retn
  4413                              <1> 
  4414                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4415                              <1> ;/////////////////////////////////////////////////////////////////////
  4416                              <1> 
  4417                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4418                              <1> ; ((Direct call instead of int 13h simulation))
  4419                              <1> ;
  4420                              <1> ;		Function in AL
  4421                              <1> ;			0 = reset
  4422                              <1> ;			1 = read
  4423                              <1> ;			2 = write
  4424                              <1> ;		Disk drive number in DL
  4425                              <1> ;			0 & 1 = floppy disks	
  4426                              <1> ;			80h .. 83h = hard disks
  4427                              <1> ;		Sector address (LBA) in ECX
  4428                              <1> ;		Buffer address in EBX
  4429                              <1> ;		R/W sector count is (always) 1
  4430                              <1> ;
  4431                              <1> ;		Return:
  4432                              <1> ;			Status in AH (>0 = error code)
  4433                              <1> ;			if CF = 1 -> error code in AH
  4434                              <1> ;			if CF = 0 -> successful
  4435                              <1> ;			AL = undefined
  4436                              <1> ;
  4437                              <1> ;		Modified registers: (only) EAX
  4438                              <1> 
  4439                              <1> ; 10/07/2022
  4440                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4441                              <1> 
  4442                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4443                              <1> ; 23/02/2015
  4444                              <1> ; 21/02/2015 (unix386.s)
  4445                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4446                              <1> ;
  4447                              <1> ; Original Source Code:
  4448                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4449                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4450                              <1> ;
  4451                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4452                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4453                              <1> ;
  4454                              <1> 
  4455                              <1> ;The wait for controller to be not busy is 10 seconds.
  4456                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4457                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4458                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4459                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4460                              <1> 
  4461                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4462                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4463                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4464                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4465                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4466                              <1> 
  4467                              <1> ;The wait for Data request on read and write longs is
  4468                              <1> ;2000 us. (?)
  4469                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4470                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4471                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4472                              <1> 
  4473                              <1> ; Port 61h (PORT_B)
  4474                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4475                              <1> 
  4476                              <1> ; 23/12/2014
  4477                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4478                              <1> 
  4479                              <1> 	; 11/07/2022
  4480                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4481                              <1> 
  4482                              <1> ;--- INT 13H -------------------------------------------------------------------
  4483                              <1> ;									       :
  4484                              <1> ; FIXED DISK I/O INTERFACE						       :
  4485                              <1> ;									       :
  4486                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4487                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4488                              <1> ;									       :
  4489                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4490                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4491                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4492                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4493                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4494                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4495                              <1> ;									       :
  4496                              <1> ;------------------------------------------------------------------------------:
  4497                              <1> ;									       :
  4498                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4499                              <1> ;									       :
  4500                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4501                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY                        :
  4502                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY                       :
  4503                              <1> ;									       :
  4504                              <1> ;------------------------------------------------------------------------------:
  4505                              <1> ;									       :
  4506                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4507                              <1> ;									       :
  4508                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4509                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4510                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4511                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4512                              <1> ;									       :
  4513                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4514                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4515                              <1> ;				 (10 BITS TOTAL)			       :
  4516                              <1> ;									       :
  4517                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4518                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4519                              <1> ;									       :
  4520                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4521                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4522                              <1> ;									       :
  4523                              <1> ;------------------------------------------------------------------------------:
  4524                              <1> ; OUTPUT								       :
  4525                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4526                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4527                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4528                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4529                              <1> ;									       :
  4530                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4531                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4532                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4533                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4534                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4535                              <1> ;		REWRITTEN.						       :
  4536                              <1> ;									       :
  4537                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4538                              <1> ;	   INPUT:							       :
  4539                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4540                              <1> ;	   OUTPUT:							       :
  4541                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4542                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4543                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4544                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4545                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4546                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4547                              <1> ;									       :
  4548                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4549                              <1> ;	INFORMATION.							       :
  4550                              <1> ;									       :
  4551                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4552                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4553                              <1> ;									       :
  4554                              <1> ;-------------------------------------------------------------------------------
  4555                              <1> 
  4556                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4557                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4558                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4559                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4560                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4561                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4562                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4563                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4564                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4565                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4566                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4567                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4568                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4569                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4570                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4571                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4572                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4573                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4574                              <1> 
  4575                              <1> ;--------------------------------------------------------
  4576                              <1> ;							:
  4577                              <1> ; FIXED DISK PARAMETER TABLE				:
  4578                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4579                              <1> ;							:
  4580                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4581                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4582                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4583                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4584                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4585                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4586                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4587                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4588                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4589                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4590                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4591                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4592                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4593                              <1> ;							:
  4594                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4595                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4596                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4597                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4598                              <1> ;							:
  4599                              <1> ;--------------------------------------------------------
  4600                              <1> 
  4601                              <1> ;--------------------------------------------------------
  4602                              <1> ;							:
  4603                              <1> ; HARDWARE SPECIFIC VALUES				:
  4604                              <1> ;							:
  4605                              <1> ;  -  CONTROLLER I/O PORT				:
  4606                              <1> ;							:
  4607                              <1> ;     > WHEN READ FROM: 				:
  4608                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4609                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4610                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4611                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4612                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4613                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4614                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4615                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4616                              <1> ;							:
  4617                              <1> ;     > WHEN WRITTEN TO:				:
  4618                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4619                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4620                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4621                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4622                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4623                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4624                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4625                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4626                              <1> ;							:
  4627                              <1> ;--------------------------------------------------------
  4628                              <1> 
  4629                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4630                              <1> ;HF1_PORT	equ	0170h	
  4631                              <1> ;HF_REG_PORT	EQU	03F6H
  4632                              <1> ;HF1_REG_PORT	equ	0376h
  4633                              <1> 
  4634                              <1> HDC1_BASEPORT	equ	1F0h
  4635                              <1> HDC2_BASEPORT	equ	170h		
  4636                              <1> 
  4637                              <1> align 2
  4638                              <1> 
  4639                              <1> ;-----		STATUS REGISTER
  4640                              <1> 
  4641                              <1> ST_ERROR	EQU	00000001B	;
  4642                              <1> ST_INDEX	EQU	00000010B	;
  4643                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4644                              <1> ST_DRQ		EQU	00001000B	;
  4645                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4646                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4647                              <1> ST_READY	EQU	01000000B	;
  4648                              <1> ST_BUSY 	EQU	10000000B	;
  4649                              <1> 
  4650                              <1> ;-----		ERROR REGISTER
  4651                              <1> 
  4652                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4653                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4654                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4655                              <1> ;		EQU	00001000B	; NOT USED
  4656                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4657                              <1> ;		EQU	00100000B	; NOT USED
  4658                              <1> ERR_DATA_ECC	EQU	01000000B
  4659                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4660                              <1> 
  4661                              <1> 
  4662                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4663                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4664                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4665                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4666                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4667                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4668                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4669                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4670                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4671                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4672                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4673                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4674                              <1> 
  4675                              <1> ;MAX_FILE	EQU	2
  4676                              <1> ;S_MAX_FILE	EQU	2
  4677                              <1> MAX_FILE	equ	4		; 22/12/2014
  4678                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4679                              <1> 
  4680                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4681                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4682                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4683                              <1> 
  4684                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4685                              <1> 
  4686                              <1> ;-----		COMMAND BLOCK REFERENCE
  4687                              <1> 
  4688                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4689                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4690                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4691                              <1> ; 19/12/2014
  4692                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4693                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4694                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4695                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4696                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4697                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4698                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4699                              <1> 
  4700                              <1> align 2
  4701                              <1> 
  4702                              <1> ;----------------------------------------------------------------
  4703                              <1> ; FIXED DISK I/O SETUP						:
  4704                              <1> ;								:
  4705                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4706                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4707                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4708                              <1> ;								:
  4709                              <1> ;----------------------------------------------------------------
  4710                              <1> 
  4711                              <1> 	; 12/07/2022
  4712                              <1> 	; 11/07/2022
  4713                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4714                              <1> 
  4715                              <1> DISK_SETUP:
  4716                              <1> 	;cli
  4717                              <1> 	;;mov	ax, ABS0 			; GET ABSOLUTE SEGMENT
  4718                              <1> 	;xor	ax, ax
  4719                              <1> 	;mov	ds, ax				; SET SEGMENT REGISTER
  4720                              <1> 	;mov	ax, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4721                              <1> 	;mov	[DISK_VECTOR], ax		; INTO INT 40H
  4722                              <1> 	;mov	ax, [ORG_VECTOR+2]
  4723                              <1> 	;mov	[DISK_VECTOR+2], ax
  4724                              <1> 	;mov	word [ORG_VECTOR], DISK_IO	; FIXED DISK HANDLER
  4725                              <1> 	;mov	[ORG_VECTOR+2], cs
  4726                              <1> 	; 1st controller (primary master, slave) - IRQ 14
  4727                              <1> 	;;mov	word [HDISK_INT], HD_INT	; FIXED DISK INTERRUPT
  4728                              <1> 	;mov	word [HDISK_INT1], HD_INT	;
  4729                              <1> 	;;mov	[HDISK_INT+2], cs
  4730                              <1> 	;mov	[HDISK_INT1+2], cs
  4731                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4732                              <1> 	;mov	word [HDISK_INT2], HD1_INT	;
  4733                              <1> 	;mov	[HDISK_INT2+2], cs
  4734                              <1> 	;
  4735                              <1> 	;;mov	word [HF_TBL_VEC], HD0_DPT	; PARM TABLE DRIVE 80
  4736                              <1> 	;;mov	word [HF_TBL_VEC+2], DPT_SEGM
  4737                              <1> 	;;mov	word [HF1_TBL_VEC], HD1_DPT	; PARM TABLE DRIVE 81
  4738                              <1> 	;;mov	word [HF1_TBL_VEC+2], DPT_SEGM
  4739                              <1> 	;push	cs
  4740                              <1> 	;pop	ds
  4741                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4742                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4743 00002036 C705[E0620000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4743 0000203E 0900                <1>
  4744                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4745                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4746 00002040 C705[E4620000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4746 00002048 0900                <1>
  4747                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4748                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4749 0000204A C705[E8620000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4749 00002052 0900                <1>
  4750                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4751                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4752 00002054 C705[EC620000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4752 0000205C 0900                <1>
  4753                              <1> 	;
  4754                              <1> 	;;in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  4755                              <1> 	;;;and	al, 0BFh
  4756                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4757                              <1> 	;;;JMP	$+2
  4758                              <1> 	;;IODELAY
  4759                              <1> 	;;out	INTB01, al
  4760                              <1> 	;;IODELAY
  4761                              <1> 	;;in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  4762                              <1> 	;;and	al, 0FBh 		; SECOND CHIP
  4763                              <1> 	;;;JMP	$+2
  4764                              <1> 	;;IODELAY
  4765                              <1> 	;;out	INTA01, al
  4766                              <1> 	;
  4767                              <1> 	;sti
  4768                              <1> 	;;push	ds			; MOVE ABS0 POINTER TO
  4769                              <1> 	;;pop	es			; EXTRA SEGMENT POINTER
  4770                              <1> 	;;;call	DDS			; ESTABLISH DATA SEGMENT
  4771                              <1> 	;;mov	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4772                              <1> 	;;mov	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4773                              <1> 	;;mov	byte [CONTROL_BYTE],0
  4774                              <1> 	;;mov	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4775                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4776                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4777                              <1> 	;mov	si, hd0_type
  4778 0000205E BE[6E5D0000]        <1> 	mov	esi, hd0_type
  4779                              <1> 	;;mov	cx, 4
  4780                              <1> 	;mov	ecx, 4
  4781                              <1> 	; 11/07/2022
  4782 00002063 29C9                <1> 	sub	ecx, ecx
  4783 00002065 B104                <1> 	mov	cl, 4
  4784                              <1> hde_l:
  4785 00002067 AC                  <1> 	lodsb
  4786 00002068 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4787 0000206A 7206                <1> 	jb	short _L4
  4788 0000206C FE05[DC620000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4789                              <1> _L4: ; 26/02/2015
  4790 00002072 E2F3                <1> 	loop	hde_l	
  4791                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4792                              <1> ;L4:
  4793                              <1> 	; 
  4794                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4795                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4796                              <1> 	;;mov 	cl, 3
  4797                              <1> 	;;
  4798                              <1> 	;;mov	dl, 80h			; CHECK THE CONTROLLER
  4799                              <1> ;;hdc_dl:
  4800                              <1> 	;;mov	ah, 14h			; USE CONTROLLER DIAGNOSTIC COMMAND
  4801                              <1> 	;;int	13h			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4802                              <1> 	;;;jc	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4803                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4804                              <1> 	;;jnc	short hdc_reset0
  4805                              <1> 	;;loop	hdc_dl
  4806                              <1> 	;;; 27/12/2014
  4807                              <1> 	;;stc
  4808                              <1> 	;;retn
  4809                              <1> 	;
  4810                              <1> ;;hdc_reset0:
  4811                              <1> 	; 18/01/2015
  4812 00002074 8A0D[DC620000]      <1> 	mov	cl, [HF_NUM]
  4813 0000207A 20C9                <1> 	and	cl, cl
  4814 0000207C 740D                <1> 	jz	short POD_DONE
  4815                              <1> 	;
  4816 0000207E B27F                <1> 	mov	dl, 7Fh
  4817                              <1> hdc_reset1:
  4818 00002080 FEC2                <1> 	inc	dl
  4819                              <1> 	;; 31/12/2015
  4820                              <1> 	;;push	dx
  4821                              <1> 	;;push	cx
  4822                              <1> 	;;push	ds
  4823                              <1> 	;;sub	ax, ax
  4824                              <1> 	;;mov	ds, ax
  4825                              <1> 	;;mov	ax, [TIMER_LOW]		; GET START TIMER COUNTS
  4826                              <1> 	;;pop	ds
  4827                              <1> 	;;mov	bx, ax
  4828                              <1> 	;;add	ax, 6*182		; 60 SECONDS* 18.2
  4829                              <1> 	;;mov	cx, ax
  4830                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4831                              <1> 	;;
  4832                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4833                              <1> 	;;call	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4834                              <1> 	;;pop	cx
  4835                              <1> 	;;pop	dx
  4836                              <1> 	;;
  4837                              <1> 	; 18/01/2015
  4838                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4839                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4840                              <1> 	;mov	ah, 5 ; ALTERNATE RESET
  4841                              <1> 	;;int	13h
  4842                              <1> 	;call	int13h
  4843                              <1> 	; 12/07/2022
  4844 00002082 30C0                <1> 	xor	al, al  ; reset
  4845 00002084 E803000000          <1> 	call	DISK_IO	
  4846                              <1> 	;
  4847 00002089 E2F5                <1> 	loop	hdc_reset1
  4848                              <1> POD_DONE:
  4849 0000208B C3                  <1> 	retn
  4850                              <1> 
  4851                              <1> ;----------------------------------------
  4852                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4853                              <1> ;----------------------------------------
  4854                              <1> 
  4855                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4856                              <1> ; ((Direct call instead of int 13h simulation))
  4857                              <1> ;
  4858                              <1> ;		Function in AL
  4859                              <1> ;			0 = reset
  4860                              <1> ;			1 = read
  4861                              <1> ;			2 = write
  4862                              <1> ;		Disk drive number in DL
  4863                              <1> ;			0 & 1 = floppy disks	
  4864                              <1> ;			80h .. 83h = hard disks
  4865                              <1> ;		Sector address (LBA) in ECX
  4866                              <1> ;		Buffer address in EBX
  4867                              <1> ;		R/W sector count is (always) 1
  4868                              <1> ;
  4869                              <1> ;		Return:
  4870                              <1> ;			Status in AH (>0 = error code)
  4871                              <1> ;			if CF = 1 -> error code in AH
  4872                              <1> ;			if CF = 0 -> successful
  4873                              <1> ;			AL = undefined
  4874                              <1> ;
  4875                              <1> ;		Modified registers: (only) EAX
  4876                              <1> 	
  4877                              <1> 
  4878                              <1> ; 11/07/2022
  4879                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4880                              <1> 
  4881                              <1> DISK_IO:
  4882                              <1> 	; 11/07/2022
  4883                              <1> 	; save registers
  4884 0000208C 57                  <1> 	push	edi			; ANY
  4885 0000208D 56                  <1> 	push	esi			; ANY
  4886 0000208E 53                  <1> 	push	ebx			; BUFFER ADDRESS
  4887 0000208F 51                  <1> 	push	ecx			; SECTOR ADDRESS (LBA)
  4888 00002090 52                  <1> 	push	edx			; DRIVE NUMBER (DL)
  4889                              <1> 
  4890                              <1> 	;cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4891                              <1> 	;;jae	short A1		; YES, HANDLE HERE
  4892                              <1> 	;;;;int	40H			; DISKETTE HANDLER
  4893                              <1> 	;;;call	int40h
  4894                              <1> 	;;jb	DISKETTE_IO_1
  4895                              <1> 	;; 24/12/2021
  4896                              <1> 	;jnb	short A1
  4897                              <1> 	;jmp	DISKETTE_IO_1
  4898                              <1> 
  4899                              <1> 	; 11/07/2022
  4900 00002091 80FA80              <1> 	cmp	dl, 80h
  4901 00002094 730B                <1> 	jae	short A1
  4902                              <1> 
  4903 00002096 E8B1F6FFFF          <1> 	call	DISKETTE_IO_1
  4904                              <1> 
  4905                              <1> DISK_IO_RTN:
  4906                              <1> 	; restore registers
  4907 0000209B 5A                  <1> 	pop	edx
  4908 0000209C 59                  <1> 	pop	ecx
  4909 0000209D 5B                  <1> 	pop	ebx
  4910 0000209E 5E                  <1> 	pop	esi
  4911 0000209F 5F                  <1> 	pop	edi
  4912 000020A0 C3                  <1> 	retn	
  4913                              <1> 
  4914                              <1> ;RET_2:
  4915                              <1> ;	retf	4			; BACK TO CALLER
  4916                              <1> 
  4917                              <1> A1:
  4918                              <1> 	; 11/07/2022
  4919                              <1> 	;sti				; ENABLE INTERRUPTS
  4920                              <1> 	;cmp	dl, (80h + S_MAX_FILE - 1)
  4921                              <1> 	;ja	short RET_2
  4922                              <1> 	
  4923                              <1> 	; 18/01/2015
  4924                              <1> 	;;or	ah, ah
  4925                              <1> 	;or	al, al ; 11/07/2022 (reset function)
  4926                              <1> 	;jz	short A3 ; 08/07/2022
  4927                              <1> 	
  4928                              <1> 	;;cmp	ah, 5  ; Alternate reset
  4929                              <1> 	;cmp	al, 5  ; 11/07/2022
  4930                              <1> 	;je	short A2
  4931                              <1> 	
  4932                              <1> 	; 11/07/2022 - no need to check
  4933                              <1> 	;		 (only kernel calls diskio functions)
  4934                              <1> 	;;cmp	ah, M1L/4 ; cmp ah, 6
  4935                              <1> 	;jb	short A3
  4936                              <1> 	;; BAD COMMAND
  4937                              <1>         ;mov     byte [DISK_STATUS1], BAD_CMD
  4938                              <1> ;RET_2:
  4939                              <1> 	;retf	4
  4940                              <1> 
  4941                              <1> 	; 11/07/2022
  4942                              <1> 	;stc
  4943                              <1> 	;retn
  4944                              <1> A2:
  4945                              <1> 	;sub	ah, ah	; Reset
  4946                              <1> 	; 11/07/2022
  4947                              <1> 	;sub	al, al
  4948                              <1> A3:
  4949                              <1> 					; SAVE REGISTERS DURING OPERATION
  4950 000020A1 C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  4951                              <1> 	
  4952                              <1> 	; 11/07/2022
  4953                              <1> 	; 08/07/2022
  4954                              <1> 	;push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  4955                              <1> 	;push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  4956                              <1> 	;push	edx
  4957                              <1> 	;push	esi
  4958                              <1> 	;push	edi
  4959                              <1> 	
  4960 000020A5 E80D000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  4961                              <1> 
  4962 000020AA C9                  <1> 	leave	; 11/07/2022
  4963                              <1> 	
  4964 000020AB 8A25[DB620000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  4965 000020B1 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  4966 000020B4 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  4967                              <1> 	
  4968                              <1> 	;pop	edi			; RESTORE REGISTERS
  4969                              <1> 	;pop	esi
  4970                              <1>       	;pop	edx
  4971                              <1> 	;pop	ecx
  4972                              <1> 	;pop	ebx
  4973                              <1> 	
  4974                              <1> 	;leave				; ADJUST (ESP) AND RESTORE (EBP)
  4975                              <1> 	
  4976                              <1> 	; 11/07/2022
  4977                              <1> 	;retf	4			; THROW AWAY SAVED FLAGS
  4978                              <1> 
  4979 000020B5 EBE4                <1> 	jmp	short DISK_IO_RTN
  4980                              <1> 
  4981                              <1> DISK_IO_CONT:
  4982                              <1> 	; 11/07/2022
  4983                              <1> 	;	INPUT:
  4984                              <1> 	;	    AL = 0 : reset
  4985                              <1> 	;	    AL = 1 : read
  4986                              <1> 	;	    Al = 2 : write
  4987                              <1> 	; 	
  4988                              <1> 	; 10/07/2022
  4989                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4990                              <1> SU0:
  4991 000020B7 C605[DB620000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  4992                              <1> 	; 10/07/2022
  4993 000020BE 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  4994                              <1> 
  4995 000020C0 8A1D[DC620000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  4996 000020C6 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  4997                              <1> 					; (get drive number as 0 to 3)
  4998 000020C9 38D3                <1> 	cmp	bl, dl
  4999                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  5000                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5001                              <1> 	; 24/12/2021
  5002 000020CB 7705                <1> 	ja	short su0_su1
  5003 000020CD E98D000000          <1> 	jmp	BAD_COMMAND
  5004                              <1> su0_su1:
  5005                              <1>         ;;03/01/2015
  5006 000020D2 29DB                <1> 	sub	ebx, ebx
  5007 000020D4 88D3                <1> 	mov	bl, dl
  5008 000020D6 883D[F0620000]      <1> 	mov	[LBAMode], bh  ; 0
  5009                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  5010                              <1> 	;jz	short su1		; no
  5011                              <1> 	;inc	byte [LBAMode]
  5012                              <1> ;su1:
  5013                              <1> 	; 21/02/2015 (32 bit modification)
  5014                              <1> 	; 04/01/2015
  5015                              <1> 	;push	ax ; ***
  5016                              <1> 	; 24/12/2021
  5017 000020DC 50                  <1> 	push	eax ; *** ; function (in AL) ; 11/07/2022
  5018                              <1> 	; 24/12/2021
  5019 000020DD 52                  <1> 	push	edx ; *
  5020 000020DE 50                  <1> 	push	eax ; function (in AL)	; 11/07/2022
  5021 000020DF E8C5030000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5022                              <1> 	; 02/02/2015
  5023 000020E4 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  5024 000020E8 66A3[625D0000]      <1> 	mov	[HF_PORT], ax
  5025 000020EE 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  5026 000020F2 668915[645D0000]    <1> 	mov	[HF_REG_PORT], dx
  5027 000020F9 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  5028                              <1> 	; 23/02/2015
  5029 000020FC A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5030 000020FE 7406                <1> 	jz 	short su1
  5031 00002100 FE05[F0620000]      <1> 	inc	byte [LBAMode] ; 1 
  5032                              <1> su1: 	 
  5033 00002106 C0E804              <1> 	shr 	al, 4
  5034 00002109 2401                <1> 	and	al, 1			
  5035 0000210B A2[665D0000]        <1> 	mov	[hf_m_s], al 
  5036                              <1> 	;
  5037                              <1> 	; 03/01/2015
  5038 00002110 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5039                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  5040 00002113 EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  5041                              <1> 					; Control Byte: (= 08h, here)
  5042                              <1> 					; bit 0 - 0
  5043                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5044                              <1> 					; bit 2 - SRST (software RESET)
  5045                              <1> 					; bit 3 - use extra heads (8 to 15)
  5046                              <1> 					;         -always set to 1-	
  5047                              <1> 					; (bits 3 to 7 are reserved
  5048                              <1> 					;          for ATA devices)
  5049 00002114 8A25[DD620000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5050 0000211A 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  5051 0000211D 08C4                <1> 	or	ah, al
  5052 0000211F 8825[DD620000]      <1> 	mov	[CONTROL_BYTE], ah	
  5053                              <1> 	; 04/01/2015
  5054                              <1> 	;pop	ax
  5055                              <1> 	; 24/12/2021
  5056 00002125 58                  <1> 	pop	eax ; function (in AL) ; 11/07/2022
  5057                              <1> 	;pop	dx ; * ;; 14/02/2015
  5058                              <1> 	; 24/12/2021
  5059 00002126 5A                  <1> 	pop	edx ; *
  5060                              <1> 	;and	ah, ah	; Reset function ?
  5061 00002127 20C0                <1> 	and	al, al	; 11/07/2022
  5062 00002129 7506                <1> 	jnz	short su2
  5063                              <1> 	;pop	ax ; ***
  5064                              <1> 	; 24/12/2021
  5065 0000212B 58                  <1> 	pop	eax ; *** 	
  5066                              <1> 	;;pop	bx
  5067 0000212C E9E5000000          <1>         jmp     DISK_RESET
  5068                              <1> su2:
  5069                              <1> 	; 11/07/2022
  5070                              <1> 	; ecx = sector address (lba)
  5071                              <1> 	;  dl = hard disk drive number (80h, 81h .. 83h)	 
  5072                              <1> 	;  al = function (0 = read, 1 = write)	
  5073                              <1> 
  5074 00002131 803D[F0620000]00    <1> 	cmp	byte [LBAMode], 0
  5075 00002138 7620                <1> 	jna	short su3 ; convert LBA address to CHS parameters
  5076                              <1> 	
  5077                              <1> ;	; 02/02/2015 (LBA read/write function calls)
  5078                              <1> ;	;cmp	ah, 1Bh
  5079                              <1> ;	cmp	ah, 3 ; 08/07/2022
  5080                              <1> ;	jb	short lbarw1
  5081                              <1> ;	;;cmp	ah, 1Ch
  5082                              <1> ;	;cmp	ah, 4 ; 08/07/2022 
  5083                              <1> ;	;ja 	short invldfnc
  5084                              <1> ;	;;pop	dx ; * ; 14/02/2015
  5085                              <1> ;	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5086                              <1> 
  5087 0000213A 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5088                              <1> 
  5089                              <1> 	; 11/07/2022
  5090                              <1> 	;; 14/02/2015
  5091                              <1> 	;mov	cl, dl ; 14/02/2015
  5092                              <1> 
  5093                              <1> 	;;mov	dx, bx
  5094                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5095                              <1> 	;;mov	bx, di
  5096                              <1> 	;mov	si, di ; Buffer offset
  5097                              <1> 
  5098                              <1> 	; 11/07/2022
  5099                              <1> 	;jmp	short lbarw2
  5100                              <1> 
  5101                              <1> ;lbarw1:
  5102                              <1> ;	; convert CHS to LBA
  5103                              <1> ;	;
  5104                              <1> ;	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5105                              <1> ;	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5106                              <1> ;	;	+ Sector - 1
  5107                              <1> ;	;push	dx ; * ;; 14/02/2015
  5108                              <1> ;	; 24/12/2021
  5109                              <1> ;	push	edx ; *
  5110                              <1> ;	;xor	dh, dh
  5111                              <1> ;	xor	edx, edx
  5112                              <1> ;	mov	dl, [ebx+14]	; sectors per track (logical)
  5113                              <1> ;	;xor	ah, ah
  5114                              <1> ;	xor	eax, eax
  5115                              <1> ;	mov	al, [ebx+2]	; heads (logical) 
  5116                              <1> ;	dec	al
  5117                              <1> ;	;inc	ax		; 0 =  256
  5118                              <1> ;	inc	eax ; 24/12/2021
  5119                              <1> ;	mul 	dx
  5120                              <1> ;		; AX = # of Heads * Sectors/Track
  5121                              <1> ;	mov	dx, cx
  5122                              <1> ;	;and	cx, 3Fh	 ; sector (1 to 63)
  5123                              <1> ;	and	ecx, 3fh
  5124                              <1> ;	xchg	dl, dh
  5125                              <1> ;	shr	dh, 6
  5126                              <1> ;		; DX = cylinder (0 to 1023)
  5127                              <1> ;	;mul 	dx
  5128                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder
  5129                              <1> ;	mul	edx
  5130                              <1> ;	dec	cl  ; sector - 1
  5131                              <1> ;	;add	ax, cx
  5132                              <1> ;	;adc	dx, 0
  5133                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  5134                              <1> ;	add	eax, ecx
  5135                              <1> ;	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5136                              <1> ;	; 24/12/2021
  5137                              <1> ;	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  5138                              <1> ;	;push	dx
  5139                              <1> ;	;push	ax
  5140                              <1> ;	push	eax
  5141                              <1> ;	mov	al, [ebx+14]  ; sectors per track (logical)	
  5142                              <1> ;	mul	ch
  5143                              <1> ;		; AX = Head * Sectors/Track
  5144                              <1> ;	cwd
  5145                              <1> ;	;pop	dx
  5146                              <1> ;	pop	edx
  5147                              <1> ;	;add	ax, dx
  5148                              <1> ;	;pop	dx
  5149                              <1> ;	;adc	dx, 0 ; add carry bit
  5150                              <1> ;	add	eax, edx
  5151                              <1> ;
  5152                              <1> ;lbarw2:
  5153                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5154                              <1> 	
  5155 0000213C 29D2                <1> 	sub	edx, edx ; 21/02/2015
  5156                              <1> 	
  5157                              <1> 	; 11/07/2022
  5158                              <1> 	;mov	dl, cl ; 21/02/2015
  5159                              <1>         
  5160 0000213E C645F800            <1> 	mov     byte [CMD_BLOCK], 0 ; Features Register
  5161                              <1> 				; NOTE: Features register (1F1h, 171h)
  5162                              <1> 				; is not used for ATA device R/W functions. 
  5163                              <1> 				; It is old/obsolete 'write precompensation'
  5164                              <1> 				; register and error register
  5165                              <1> 				; for old ATA/IDE devices.
  5166                              <1> 	; 18/01/2014
  5167                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  5168 00002142 8A0D[665D0000]      <1> 	mov	cl, [hf_m_s]
  5169                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  5170                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  5171                              <1> 				; bit 6 = 1 = LBA mode
  5172                              <1> 				; bit 7 = 1
  5173 00002148 80C90E              <1> 	or	cl, 0Eh ; 1110b
  5174                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  5175 0000214B 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  5176 00002150 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  5177                              <1> 	;or	dh, ch
  5178 00002153 09C8                <1> 	or	eax, ecx	
  5179                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  5180                              <1> 				  ; (Sector Number Register)
  5181                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  5182                              <1> 				  ; (Cylinder Low Register)
  5183                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  5184                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  5185                              <1> 				  ; (Cylinder High Register)
  5186                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  5187                              <1> 				  ; (Drive/Head Register)
  5188                              <1> 	
  5189                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  5190 00002155 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  5191                              <1> 	;14/02/2015
  5192                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  5193 00002158 EB3E                <1> 	jmp	short su4
  5194                              <1> su3:
  5195                              <1> 	; 02/02/2015 
  5196                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  5197                              <1> 	;cmp 	ah, 14h
  5198                              <1> 	;jna 	short chsfnc
  5199                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5200                              <1> 	;cmp	ah, 2
  5201                              <1> 	;jna	short chsfnc
  5202                              <1> 	; 11/07/2022 
  5203                              <1> 	; (al = function, read = 1 or write = 2)
  5204 0000215A 3C02                <1> 	cmp	al, 2 
  5205 0000215C 760B                <1> 	jna	short chsfnc
  5206                              <1> invldfnc:
  5207                              <1>         ; 14/02/2015  
  5208                              <1> 	;pop	es ; **
  5209                              <1>         ;pop	ax ; ***
  5210                              <1>         ; 24/12/2021
  5211 0000215E 58                  <1> 	pop	eax ; ***
  5212                              <1> 	;;jmp	short BAD_COMMAND_POP
  5213                              <1> 	; 11/07/2022
  5214                              <1>         ;jmp     short BAD_COMMAND
  5215                              <1> 
  5216                              <1> 	; 11/07/2022
  5217                              <1> BAD_COMMAND:
  5218 0000215F C605[DB620000]01    <1> 	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5219                              <1> 	;mov	al, 0
  5220 00002166 28C0                <1> 	sub	al, al ; 0
  5221 00002168 C3                  <1> 	retn
  5222                              <1> 
  5223                              <1> chsfnc:	
  5224 00002169 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5225 0000216D 66C1E802            <1> 	shr	ax, 2
  5226 00002171 8845F8              <1> 	mov	[CMD_BLOCK], al
  5227                              <1> 	;
  5228                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5229                              <1> 	;;push	edx ; *
  5230                              <1> 	;;mov	dx, [HF_REG_PORT]
  5231                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5232                              <1> 	;;pop	edx ; * 
  5233                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5234                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5235                              <1> 	;;or	ah, al
  5236                              <1> 	;;mov	[CONTROL_BYTE], ah
  5237                              <1> 	;
  5238 00002174 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5239 00002176 243F                <1> 	and	al, 3Fh
  5240 00002178 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5241 0000217B 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5242 0000217E 88C8                <1> 	mov	al, cl
  5243 00002180 C0E806              <1> 	shr	al, 6
  5244 00002183 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5245                              <1> 	;;05/01/2015
  5246                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5247 00002186 A0[665D0000]        <1> 	mov	al, [hf_m_s]
  5248 0000218B C0E004              <1> 	shl	al, 4
  5249 0000218E 80E60F              <1> 	and	dh, 0Fh			; HEAD NUMBER
  5250 00002191 08F0                <1> 	or	al, dh
  5251 00002193 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5252 00002195 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5253                              <1> su4:
  5254                              <1> 	;; 14/02/2015
  5255                              <1>         ;;pop	ax
  5256                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5257                              <1>         ;;push	ax
  5258                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5259                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5260                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5261                              <1> 	;pop	ax ; ***
  5262                              <1> 	; 24/12/2021
  5263 00002198 58                  <1> 	pop	eax ; *** ; function (in AL) ; 11/07/2022
  5264                              <1> 	
  5265                              <1> 	;mov	[CMD_BLOCK+1], al
  5266 00002199 C645F901            <1>         mov	byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w)
  5267                              <1> 
  5268                              <1> 	; 11/07/2022
  5269                              <1> 	;mov	ebx, esi
  5270                              <1> 	; (esi = buffer address)	
  5271                              <1> 
  5272 0000219D 3C02                <1> 	cmp	al, 2
  5273 0000219F 742D                <1> 	je	short DISK_WRITE
  5274                              <1> 
  5275                              <1> 	;jmp	short DISK_READ
  5276                              <1> 
  5277                              <1> ;	;xor	ebx, ebx
  5278                              <1> ;	;mov	bl, ah
  5279                              <1> ;
  5280                              <1> ;       ;xor	bh, bh
  5281                              <1> ;       ;sal	bx, 1
  5282                              <1> ;       sal	bx, 2	; 32 bit offset (21/02/2015)
  5283                              <1> ;	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5284                              <1> ;       ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5285                              <1> ;       ;;jnb	short BAD_COMMAND_POP
  5286                              <1> ;   	; 08/07/2022
  5287                              <1> ;	;cmp	ebx, M1L
  5288                              <1> ;	;jnb	short BAD_COMMAND
  5289                              <1> ;
  5290                              <1> ;	xchg	ebx, esi
  5291                              <1> ;
  5292                              <1> ;	;;;pop	ax			; RESTORE AX
  5293                              <1> ;	;;;pop	bx			; AND DATA ADDRESS
  5294                              <1> ;	
  5295                              <1> ;	;;push	cx
  5296                              <1> ;	;;push	ax			; ADJUST ES:BX
  5297                              <1> ;	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5298                              <1> ;	;shr	cx, 4
  5299                              <1> ;	;mov	ax, es
  5300                              <1> ;	;add	ax, cx
  5301                              <1> ;	;mov	es, ax
  5302                              <1> ;	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5303                              <1> ;	;;pop	ax
  5304                              <1> ;	;;pop	cx
  5305                              <1> ;
  5306                              <1> ;	jmp	dword [esi+M1]
  5307                              <1> 
  5308                              <1> ;;BAD_COMMAND_POP:
  5309                              <1> ;;	pop	ax
  5310                              <1> ;;	pop	bx
  5311                              <1> ;
  5312                              <1> ;	; 11/07/2022
  5313                              <1> ;BAD_COMMAND:
  5314                              <1> ;	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5315                              <1> ;	;mov	al, 0
  5316                              <1> ;	sub	al, al ; 0
  5317                              <1> ;	retn
  5318                              <1> 
  5319                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5320                              <1> 
  5321                              <1> ;----------------------------------------
  5322                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5323                              <1> ;----------------------------------------
  5324                              <1> ; 
  5325                              <1> DISK_READ:
  5326 000021A1 C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5327                              <1>         ;jmp	COMMANDI
  5328                              <1> 
  5329                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5330                              <1> 
  5331                              <1> ;----------------------------------------
  5332                              <1> ; COMMANDI				:
  5333                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5334                              <1> ;	NSECTOR RETURNS ZERO		:
  5335                              <1> ;----------------------------------------
  5336                              <1> COMMANDI:
  5337                              <1> 	; 11/07/2022 
  5338                              <1> 	;	(check 64K boundary is not needed)
  5339                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5340                              <1> 	;jc	short CMD_ABORT
  5341                              <1> 	
  5342                              <1> 	;mov	di, bx
  5343                              <1> 	; 11/07/2022
  5344                              <1> 	; (esi = buffer address)
  5345                              <1> 	;mov	edi, ebx ; 21/02/2015
  5346 000021A5 89F7                <1> 	mov	edi, esi ; 11/07/2022	
  5347                              <1> 
  5348 000021A7 E8A8010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5349 000021AC 751F                <1> 	jnz	short CMD_ABORT
  5350                              <1> CMD_I1:
  5351 000021AE E813020000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5352 000021B3 7518                <1> 	jnz	short TM_OUT		; TIME OUT
  5353                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5354                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5355 000021B5 29C9                <1> 	sub	ecx, ecx
  5356 000021B7 FEC5                <1> 	inc	ch
  5357                              <1> 	; ecx = 256
  5358                              <1> 	;mov	dx, HF_PORT
  5359 000021B9 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5360 000021C0 FA                  <1> 	cli
  5361 000021C1 FC                  <1> 	cld
  5362 000021C2 F3666D              <1> 	rep	insw			; GET THE SECTOR
  5363 000021C5 FB                  <1> 	sti
  5364                              <1> 	
  5365                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5366                              <1> 	;jz	short CMD_I3
  5367                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5368                              <1> 	;jc	short TM_OUT
  5369                              <1> 	;;mov	dx, HF_PORT
  5370                              <1> 	;mov	dx,[HF_PORT]
  5371                              <1> 	;xor	ecx, ecx	
  5372                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5373                              <1> 	;mov	cl, 4
  5374                              <1> ;CMD_I2: 
  5375                              <1> 	;inc	al, dx
  5376                              <1> 	;mov 	[edi], al ; 21/02/2015
  5377                              <1> 	;inc	edi
  5378                              <1> 	;loop	CMD_I2
  5379                              <1> CMD_I3: 
  5380 000021C6 E817010000          <1> 	call	CHECK_STATUS
  5381 000021CB 7500                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5382                              <1> 	; 11/07/2022
  5383                              <1> 	; (sector count = 1)
  5384                              <1> 	;dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5385                              <1> 	;jnz	SHORT CMD_I1
  5386                              <1> CMD_ABORT:
  5387                              <1> TM_OUT: 
  5388 000021CD C3                  <1> 	retn
  5389                              <1> 
  5390                              <1> ;---------------------------------------------------
  5391                              <1> 
  5392                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5393                              <1> 
  5394                              <1> ;----------------------------------------
  5395                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5396                              <1> ;----------------------------------------
  5397                              <1> 
  5398                              <1> DISK_WRITE:
  5399 000021CE C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5400                              <1>         ;JMP	COMMANDO
  5401                              <1> 
  5402                              <1> ; 16/07/2022
  5403                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5404                              <1> 
  5405                              <1> ;----------------------------------------
  5406                              <1> ; COMMANDO				:
  5407                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5408                              <1> ;	NSECTOR RETURNS ZERO		:
  5409                              <1> ;----------------------------------------
  5410                              <1> COMMANDO:
  5411                              <1> 	; 11/07/2022 
  5412                              <1> 	;	(check 64K boundary is not needed)
  5413                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5414                              <1> 	;jc	short CMD_ABORT
  5415                              <1> CMD_OF:
  5416                              <1> 	; 11/07/2022
  5417                              <1> 	; (esi = ebx = buffer address)
  5418                              <1> 	;mov	esi, ebx ; 21/02/2015
  5419 000021D2 E87D010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5420 000021D7 75F4                <1> 	jnz	short CMD_ABORT
  5421 000021D9 E83F020000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5422 000021DE 72ED                <1> 	jc	short TM_OUT		; TOO LONG
  5423                              <1> CMD_O1:
  5424                              <1> 	; 16/07/2022
  5425 000021E0 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5426                              <1> 
  5427                              <1> 	; 10/07/2022
  5428                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5429 000021E7 31C9                <1> 	xor	ecx, ecx
  5430 000021E9 FEC5                <1> 	inc	ch
  5431                              <1> 	; ecx = 256
  5432 000021EB FA                  <1> 	cli
  5433 000021EC FC                  <1> 	cld
  5434 000021ED F3666F              <1> 	rep	outsw
  5435 000021F0 FB                  <1> 	sti
  5436                              <1> 
  5437                              <1> 	; 10/07/2022
  5438                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5439                              <1> 	;jz	short CMD_O3
  5440                              <1> 	;
  5441                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5442                              <1> 	;jc	short TM_OUT
  5443                              <1> 	;;mov	dx, HF_PORT
  5444                              <1> 	;mov	dx, [HF_PORT]
  5445                              <1> 	;sub	ecx, ecx	
  5446                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5447                              <1> 	;mov	cl, 4
  5448                              <1> ;CMD_O2:
  5449                              <1> 	;;lodsb
  5450                              <1> 	;mov	al, [esi]
  5451                              <1> 	;out	dx, al
  5452                              <1> 	;inc	esi
  5453                              <1> 	;loop	CMD_O2
  5454                              <1> 
  5455                              <1> CMD_O3:
  5456 000021F1 E8D0010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5457 000021F6 75D5                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5458 000021F8 E8E5000000          <1> 	call	CHECK_STATUS
  5459 000021FD 75CE                <1> 	jnz	short CMD_ABORT
  5460                              <1> 
  5461                              <1> 	; 11/07/2022
  5462                              <1> 	; (sector count = 1)
  5463                              <1> 	;test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5464                              <1> 	;jnz	short CMD_O1
  5465                              <1> 	
  5466                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5467 000021FF 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5468 00002206 80C202              <1> 	add	dl, 2
  5469                              <1> 	;inc	dl
  5470                              <1> 	;inc	dl
  5471 00002209 EC                  <1> 	in	al, dx			;
  5472 0000220A A8FF                <1> 	test	al, 0FFh 		;
  5473 0000220C 7407                <1> 	jz	short CMD_O4		; COUNT = 0  OK
  5474 0000220E C605[DB620000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5475                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5476                              <1> CMD_O4:
  5477 00002215 C3                  <1> 	retn
  5478                              <1> 
  5479                              <1> ; 10/07/2022
  5480                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5481                              <1> 
  5482                              <1> ;----------------------------------------
  5483                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5484                              <1> ;----------------------------------------
  5485                              <1> 
  5486                              <1> ; 18-1-2015 : one controller reset (not other one)
  5487                              <1> 
  5488                              <1> DISK_RESET:
  5489 00002216 FA                  <1> 	cli
  5490 00002217 E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5491                              <1> 	;JMP	$+2
  5492                              <1> 	IODELAY
  2128 00002219 EB00                <2>  jmp short $+2
  2129 0000221B EB00                <2>  jmp short $+2
  5493                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5494 0000221D 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5495 0000221F E6A1                <1> 	out	INTB01, al
  5496 00002221 FB                  <1> 	sti				; START INTERRUPTS
  5497                              <1> 	; 14/02/2015
  5498                              <1> 	;mov	di, dx
  5499                              <1> 	; 24/12/2021
  5500 00002222 89D7                <1> 	mov	edi, edx	
  5501                              <1> 	; 04/01/2015
  5502                              <1> 	;xor	di,di
  5503                              <1> drst0:
  5504 00002224 B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5505                              <1> 	;mov	dx, HF_REG_PORT
  5506 00002226 668B15[645D0000]    <1> 	mov	dx, [HF_REG_PORT]
  5507 0000222D EE                  <1> 	out	dx, al			; RESET
  5508                              <1> ;	mov	cx, 10			; DELAY COUNT
  5509                              <1> ;DRD:	dec	cx
  5510                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5511                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5512                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5513                              <1> 	; 10/07/2022
  5514 0000222E 29C9                <1> 	sub	ecx, ecx
  5515 00002230 B102                <1> 	mov	cl, 2
  5516 00002232 E87CF2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5517                              <1>                                         ; 40 micro seconds)
  5518 00002237 A0[DD620000]        <1> 	mov	al, [CONTROL_BYTE]
  5519 0000223C 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5520 0000223E EE                  <1> 	out	dx, al			; TURN RESET OFF
  5521 0000223F E8B2010000          <1> 	call	NOT_BUSY
  5522 00002244 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5523 00002246 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5524 0000224D FEC2                <1> 	inc	dl  ; HF_PORT+1
  5525                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5526                              <1>         ;mov	cl, 10
  5527                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5528                              <1> 	; 10/07/2022
  5529                              <1> 	;xor	ecx, ecx
  5530 0000224F B10A                <1> 	mov	cl, 10 
  5531                              <1> drst1:
  5532 00002251 EC                  <1> 	in	al, dx			; GET RESET STATUS
  5533 00002252 3C01                <1> 	cmp	al, 1
  5534                              <1> 	; 04/01/2015
  5535 00002254 740C                <1> 	jz	short drst2
  5536                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5537                              <1>         	; Drive/Head Register - bit 4
  5538                              <1> 	;loop	drst1
  5539                              <1> 	; 10/07/2022
  5540 00002256 FEC9                <1> 	dec	cl
  5541 00002258 75F7                <1> 	jnz	short drst1
  5542                              <1> DRERR:	
  5543 0000225A C605[DB620000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5544 00002261 C3                  <1> 	retn
  5545                              <1> drst2:
  5546                              <1> 	; 14/02/2015
  5547                              <1> 	;mov	dx, di
  5548                              <1> 	; 24/12/2021
  5549 00002262 89FA                <1> 	mov	edx, edi
  5550                              <1> ;drst3:
  5551                              <1> ;	; 05/01/2015
  5552                              <1> ;	shl 	di, 1
  5553                              <1> ;	; 04/01/2015
  5554                              <1> ;	mov	ax, [di+hd_cports]
  5555                              <1> ;	cmp	ax, [HF_REG_PORT]
  5556                              <1> ;	je	short drst4
  5557                              <1> ;	mov	[HF_REG_PORT], ax
  5558                              <1> ;	; 03/01/2015
  5559                              <1> ;	mov	ax, [di+hd_ports]
  5560                              <1> ;       mov     [HF_PORT], ax
  5561                              <1> ;	; 05/01/2014
  5562                              <1> ;	shr	di, 1
  5563                              <1> ;	; 04/01/2015
  5564                              <1> ;	jmp	short drst0	; reset other controller
  5565                              <1> ;drst4:
  5566                              <1> ;	; 05/01/2015
  5567                              <1> ;	shr	di, 1
  5568                              <1> ;	mov	al, [di+hd_dregs]
  5569                              <1> ;	and	al, 10h ; bit 4 only
  5570                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5571                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5572                              <1> 	;
  5573 00002264 A0[665D0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5574 00002269 A801                <1> 	test	al, 1
  5575                              <1> 	;jnz	short drst6
  5576 0000226B 7516                <1>         jnz     short drst4
  5577 0000226D 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5578                              <1> ;drst5:
  5579                              <1> drst3:
  5580 00002271 E813000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5581                              <1> 	;mov	dx, di
  5582 00002276 E8A3000000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5583                              <1> 	; 04/01/2014
  5584                              <1> ;	inc	di
  5585                              <1> ;	mov	dx, di
  5586                              <1> ;	cmp	dl, [HF_NUM]
  5587                              <1> ;	jb	short drst3
  5588                              <1> ;DRE:
  5589 0000227B C605[DB620000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5590 00002282 C3                  <1> 	retn
  5591                              <1> ;drst6:
  5592                              <1> drst4:		; Drive/Head Register - bit 4
  5593 00002283 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5594                              <1>         ;jmp    short drst5
  5595 00002287 EBE8                <1>         jmp     short drst3
  5596                              <1> 
  5597                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5598                              <1> 
  5599                              <1> ;----------------------------------------
  5600                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5601                              <1> ;----------------------------------------
  5602                              <1> 	; 03/01/2015
  5603                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5604                              <1> 	; logical sector per logical track
  5605                              <1> 	; and logical heads - 1 would be set but
  5606                              <1> 	; it is seen as it will be good
  5607                              <1> 	; if physical parameters will be set here
  5608                              <1> 	; because, number of heads <= 16.
  5609                              <1> 	; (logical heads usually more than 16)
  5610                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5611                              <1> 	;	== INT 13h physical parameters
  5612                              <1> 
  5613                              <1> ;INIT_DRV:
  5614                              <1> ;	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5615                              <1> ;	call	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5616                              <1> ;	mov	al, [es:bx+2]		; GET NUMBER OF HEADS
  5617                              <1> ;	dec	al			; CONVERT TO 0-INDEX
  5618                              <1> ;	mov	ah, [CMD_BLOCK+5] 	; GET SDH REGISTER
  5619                              <1> ;	and	ah, 0F0h 		; CHANGE HEAD NUMBER
  5620                              <1> ;	or	ah, al			; TO MAX HEAD
  5621                              <1> ;	mov	[CMD_BLOCK+5], ah
  5622                              <1> ;	mov	al, [es:bx+14]		; MAX SECTOR NUMBER
  5623                              <1> ;	mov	[CMD_BLOCK+1], al
  5624                              <1> ;	sub	ax, ax
  5625                              <1> ;	mov	[CMD_BLOCK+3], al 	; ZERO FLAGS
  5626                              <1> ;	call	COMMAND 		; TELL CONTROLLER
  5627                              <1> ;	jnz	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5628                              <1> ;	call	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5629                              <1> ;	jnz	short INIT_EXIT		; TIME OUT
  5630                              <1> ;	call	CHECK_STATUS
  5631                              <1> ;INIT_EXIT:
  5632                              <1> ;	retn
  5633                              <1> 
  5634                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5635                              <1> 
  5636                              <1> ; 04/01/2015
  5637                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5638                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5639                              <1> INIT_DRV:
  5640                              <1> 	;xor	ah, ah
  5641 00002289 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5642 0000228B B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5643 0000228D 3825[F0620000]      <1>         cmp     [LBAMode], ah   ; 0
  5644 00002293 7702                <1> 	ja	short idrv0
  5645 00002295 B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5646                              <1> idrv0:
  5647                              <1> 	; DL = drive number (0 based)
  5648 00002297 E80D020000          <1> 	call	GET_VEC
  5649                              <1> 	;push	bx
  5650 0000229C 53                  <1> 	push	ebx ; 21/02/2015
  5651                              <1> 	;add	bx, ax
  5652 0000229D 01C3                <1> 	add	ebx, eax
  5653                              <1> 	;; 05/01/2015
  5654 0000229F 8A25[665D0000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5655                              <1> 	;;and 	ah, 1 
  5656 000022A5 C0E404              <1> 	shl	ah, 4
  5657 000022A8 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5658                              <1> 	;mov	al, [es:bx]
  5659 000022AB 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5660 000022AD FEC8                <1> 	dec	al	 ; last head number 
  5661                              <1> 	;and	al, 0Fh
  5662 000022AF 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5663                              <1> 	;
  5664 000022B1 C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5665 000022B5 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5666                              <1> 	;pop	bx
  5667 000022B8 5B                  <1> 	pop	ebx
  5668 000022B9 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5669 000022BB B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5670 000022BD 803D[F0620000]00    <1> 	cmp	byte [LBAMode], 0
  5671 000022C4 7702                <1> 	ja	short idrv1
  5672 000022C6 B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5673                              <1> idrv1:
  5674                              <1> 	;xor	ah, ah
  5675                              <1> 	;add	bx, ax
  5676 000022C8 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5677                              <1> 	;mov	al, [es:bx]
  5678                              <1> 			; sector number
  5679 000022CA 8A03                <1> 	mov	al, [ebx]
  5680 000022CC 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5681 000022CF 28C0                <1> 	sub	al, al
  5682 000022D1 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5683 000022D4 E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5684 000022D9 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5685 000022DB E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5686 000022E0 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5687                              <1> 	;call	CHECK_STATUS
  5688                              <1> 	;jmp	short CHECK_STATUS
  5689                              <1> ;INIT_EXIT:
  5690                              <1> 	;retn
  5691                              <1> 
  5692                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5693                              <1> 
  5694                              <1> ;----------------------------------------
  5695                              <1> ;	CHECK FIXED DISK STATUS 	:
  5696                              <1> ;----------------------------------------
  5697                              <1> CHECK_STATUS:
  5698 000022E2 E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5699                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5700                              <1> 	; 10/07/2022
  5701 000022E7 7510                <1> 	jnz	short CHECK_S2
  5702 000022E9 A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5703 000022EB 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5704 000022ED E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5705                              <1> CHECK_S1:
  5706 000022F2 803D[DB620000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5707                              <1> CHECK_S2:
  5708                              <1> INIT_EXIT:	; 10/07/2022
  5709 000022F9 C3                  <1> 	retn
  5710                              <1> 
  5711                              <1> ;----------------------------------------
  5712                              <1> ;	TEST DISK READY      (AH = 10H) :
  5713                              <1> ;----------------------------------------
  5714                              <1> 
  5715                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5716 000022FA E8F7000000          <1> 	call	NOT_BUSY
  5717 000022FF 751C                <1> 	jnz	short TR_EX
  5718 00002301 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5719 00002304 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5720 0000230B 80C206              <1> 	add	dl,6
  5721 0000230E EE                  <1> 	out	dx, al
  5722 0000230F E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5723 00002314 7507                <1> 	jnz	short TR_EX
  5724 00002316 C605[DB620000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5725                              <1> TR_EX:	
  5726 0000231D C3                  <1> 	retn
  5727                              <1> 
  5728                              <1> ;----------------------------------------
  5729                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5730                              <1> ;----------------------------------------
  5731                              <1> 
  5732                              <1> HDISK_RECAL:
  5733 0000231E C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5734 00002322 E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5735 00002327 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5736 00002329 E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5737 0000232E 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5738 00002330 E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5739 00002335 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5740                              <1> RECAL_X:
  5741 00002337 E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5742 0000233C 803D[DB620000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5743 00002343 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5744 00002345 C605[DB620000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5745                              <1> RECAL_EXIT:
  5746 0000234C 803D[DB620000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5747 00002353 C3                  <1> 	retn
  5748                              <1> 
  5749                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5750                              <1> 
  5751                              <1> ;--------------------------------------------------------
  5752                              <1> ; COMMAND						:
  5753                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5754                              <1> ; OUTPUT						:
  5755                              <1> ;	BL = STATUS					:
  5756                              <1> ;	BH = ERROR REGISTER				:
  5757                              <1> ;--------------------------------------------------------
  5758                              <1> 
  5759                              <1> COMMAND:
  5760                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5761                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5762                              <1> COMMAND1:
  5763                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5764 00002354 E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5765                              <1> 	;;pop	ecx
  5766                              <1> 	;pop	ebx ; 10/07/2022
  5767 00002359 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5768 0000235B 803D[DB620000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5769                              <1> 	;jz	short CMD_TIMEOUT
  5770                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5771                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5772 00002362 7507                <1> 	jne	short COMMAND4
  5773                              <1> CMD_TIMEOUT:
  5774 00002364 C605[DB620000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5775                              <1> COMMAND4:
  5776                              <1> 	;;pop	ebx ; 10/07/2022
  5777 0000236B 803D[DB620000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5778 00002372 C3                  <1> 	retn
  5779                              <1> COMMAND2:
  5780                              <1> 	;;pop	ebx ; 10/07/2022
  5781                              <1> 	;push	edi ; 10/07/2022
  5782 00002373 C605[D6620000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5783 0000237A FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5784 0000237B E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5785                              <1> 	;and	al, 0BFh
  5786 0000237D 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5787                              <1> 	;JMP	$+2
  5788                              <1> 	IODELAY
  2128 0000237F EB00                <2>  jmp short $+2
  2129 00002381 EB00                <2>  jmp short $+2
  5789 00002383 E6A1                <1> 	out	INTB01, al
  5790 00002385 E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5791 00002387 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5792                              <1> 	;JMP	$+2
  5793                              <1> 	IODELAY
  2128 00002389 EB00                <2>  jmp short $+2
  2129 0000238B EB00                <2>  jmp short $+2
  5794 0000238D E621                <1> 	out	INTA01, al
  5795 0000238F FB                  <1> 	sti
  5796                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5797                              <1> 	; 10/07/2022
  5798 00002390 31C9                <1> 	xor	ecx, ecx
  5799                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5800 00002392 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5801 00002399 FEC2                <1> 	inc	dl
  5802 0000239B F605[DD620000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5803 000023A2 7411                <1> 	jz	short COMMAND3
  5804 000023A4 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5805 000023A7 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5806 000023A9 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5807 000023AB 7208                <1> 	jb	short COMMAND3
  5808 000023AD 3C40                <1> 	cmp	al, 40h
  5809 000023AF 7704                <1> 	ja	short COMMAND3
  5810 000023B1 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5811                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5812                              <1> COMMAND3:
  5813                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5814                              <1> 	; 10/07/2022
  5815 000023B5 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5816 000023B9 EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5817                              <1> 	IODELAY
  2128 000023BA EB00                <2>  jmp short $+2
  2129 000023BC EB00                <2>  jmp short $+2
  5818                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5819                              <1> 	; 10/07/2022
  5820 000023BE 41                  <1> 	inc	ecx
  5821                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5822 000023BF 42                  <1> 	inc	edx   ; 10/07/2022	
  5823                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5824                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5825 000023C0 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5826 000023C3 72F0                <1> 	jb	short COMMAND3
  5827                              <1> 	;pop	edi ; 10/07/2022
  5828 000023C5 C3                  <1> 	retn				; ZERO FLAG IS SET
  5829                              <1> 
  5830                              <1> ;CMD_TIMEOUT:
  5831                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5832                              <1> ;COMMAND4:
  5833                              <1> ;	pop	ebx
  5834                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5835                              <1> ;	retn
  5836                              <1> 
  5837                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5838                              <1> 
  5839                              <1> ;----------------------------------------
  5840                              <1> ;	WAIT FOR INTERRUPT		:
  5841                              <1> ;----------------------------------------
  5842                              <1> ;WAIT:
  5843                              <1> _WAIT:
  5844 000023C6 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5845                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5846                              <1> 	;clc
  5847                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5848                              <1> 	;int	15h
  5849                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5850                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5851                              <1> 
  5852                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5853                              <1> 	;; 21/02/2015
  5854                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5855                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5856 000023C7 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5857                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5858                              <1> ;-----	WAIT LOOP
  5859                              <1> 
  5860                              <1> WT1:	
  5861                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5862 000023CC F605[D6620000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5863                              <1> 	;loopz	WT1
  5864 000023D3 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5865                              <1> 	;dec	bl
  5866                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5867                              <1> 
  5868                              <1> WT1_hi:
  5869 000023D5 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5870 000023D7 A810                <1> 	test	al, 10h			; transition on memory
  5871 000023D9 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5872                              <1> WT1_lo:
  5873 000023DB E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5874 000023DD A810                <1> 	test	al, 10h			
  5875 000023DF 74FA                <1> 	jz	short WT1_lo
  5876 000023E1 E2E9                <1> 	loop	WT1
  5877                              <1> 	;;or	bl, bl
  5878                              <1> 	;;jz	short WT2	
  5879                              <1> 	;;dec	bl
  5880                              <1> 	;;jmp	short WT1
  5881                              <1> 	;dec	bl
  5882                              <1> 	;jnz	short WT1	
  5883                              <1> WT2:	
  5884                              <1> 	; 10/07/2022
  5885                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5886 000023E3 B080                <1> 	mov	al, TIME_OUT
  5887 000023E5 EB07                <1> 	jmp	short WT4
  5888                              <1> WT3:
  5889                              <1> 	;mov	byte [DISK_STATUS1], 0
  5890                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5891 000023E7 28C0                <1> 	sub	al, al ; 0
  5892 000023E9 A2[D6620000]        <1> 	mov	byte [HF_INT_FLAG], al
  5893                              <1> WT4:
  5894                              <1> NB2:	
  5895 000023EE A2[DB620000]        <1> 	mov	byte [DISK_STATUS1], al
  5896                              <1> 
  5897                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5898 000023F3 20C0                <1> 	and	al, al
  5899                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5900 000023F5 C3                  <1> 	retn
  5901                              <1> 
  5902                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5903                              <1> 
  5904                              <1> ;----------------------------------------
  5905                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5906                              <1> ;----------------------------------------
  5907                              <1> NOT_BUSY:
  5908 000023F6 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5909                              <1> 	;push	ebx
  5910                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5911 000023F7 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5912 000023FE 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  5913                              <1> 	;mov	bl, DELAY_1
  5914                              <1> 					; wait for 10 seconds
  5915                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  5916                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  5917                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  5918 00002401 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  5919                              <1> 	;
  5920                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  5921                              <1> NB1:	
  5922 00002406 EC                  <1> 	in	al, dx			; CHECK STATUS
  5923                              <1> 	;test	al, ST_BUSY
  5924 00002407 2480                <1> 	and	al, ST_BUSY
  5925                              <1> 	;loopnz NB1
  5926 00002409 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  5927                              <1> 	;dec	bl			
  5928                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  5929                              <1> 
  5930                              <1> NB1_hi: 
  5931 0000240B E461                <1> 	in	al, SYS1		; wait for hi to lo
  5932 0000240D A810                <1> 	test	al, 010h		; transition on memory
  5933 0000240F 75FA                <1> 	jnz	short NB1_hi		; refresh.
  5934                              <1> NB1_lo: 
  5935 00002411 E461                <1> 	in	al, SYS1
  5936 00002413 A810                <1> 	test	al, 010h
  5937 00002415 74FA                <1> 	jz	short NB1_lo
  5938 00002417 E2ED                <1> 	loop	NB1
  5939                              <1> 	;dec	bl
  5940                              <1> 	;jnz	short NB1
  5941                              <1> 	;
  5942                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  5943                              <1> 	;;jb	short NB1
  5944                              <1> 	;
  5945                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5946                              <1> 	;jmp	short NB3
  5947 00002419 B080                <1> 	mov	al, TIME_OUT
  5948                              <1> ;NB2:	
  5949 0000241B EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  5950                              <1> 
  5951                              <1> ;	;mov	byte [DISK_STATUS1], 0
  5952                              <1> ;;NB3:	
  5953                              <1> ;	;pop	ebx
  5954                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  5955                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5956                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  5957                              <1> ;	retn
  5958                              <1> 
  5959                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5960                              <1> 
  5961                              <1> ;----------------------------------------
  5962                              <1> ;	WAIT FOR DATA REQUEST		:
  5963                              <1> ;----------------------------------------
  5964                              <1> WAIT_DRQ:
  5965                              <1> 	;mov	cx, DELAY_3
  5966                              <1> 	;mov	dx, HF_PORT+7
  5967 0000241D 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  5968 00002424 80C207              <1> 	add	dl, 7
  5969                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  5970                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  5971                              <1> 					; (but it is written as 2000
  5972                              <1> 					; micro seconds in ATORGS.ASM file
  5973                              <1> 					; of Award Bios - 1999, D1A0622)
  5974 00002427 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  5975                              <1> WQ_1:
  5976 0000242C EC                  <1> 	in	al, dx			; GET STATUS
  5977 0000242D A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  5978 0000242F 7516                <1> 	jnz	short WQ_OK
  5979                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  5980                              <1> WQ_hi:	
  5981 00002431 E461                <1> 	in	al, SYS1		; wait for hi to lo
  5982 00002433 A810                <1> 	test	al, 010h		; transition on memory
  5983 00002435 75FA                <1> 	jnz	short WQ_hi		; refresh.
  5984                              <1> WQ_lo:  
  5985 00002437 E461                <1> 	in	al, SYS1
  5986 00002439 A810                <1> 	test	al, 010h
  5987 0000243B 74FA                <1> 	jz	short WQ_lo
  5988 0000243D E2ED                <1> 	loop	WQ_1
  5989                              <1> 
  5990 0000243F C605[DB620000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  5991 00002446 F9                  <1> 	stc
  5992                              <1> WQ_OK:
  5993 00002447 C3                  <1> 	retn
  5994                              <1> ;WQ_OK:
  5995                              <1> 	;clc
  5996                              <1> 	;retn
  5997                              <1> 
  5998                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5999                              <1> 
  6000                              <1> ;----------------------------------------
  6001                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  6002                              <1> ;----------------------------------------
  6003                              <1> CHECK_ST:
  6004                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  6005 00002448 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]
  6006 0000244F 80C207              <1> 	add	dl, 7
  6007 00002452 EC                  <1> 	in	al, dx
  6008 00002453 A2[D5620000]        <1> 	mov	[HF_STATUS], al
  6009                              <1> 	;mov	ah, 0
  6010 00002458 28E4                <1> 	sub	ah, ah ; 0
  6011 0000245A A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  6012 0000245C 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  6013 0000245E B4CC                <1> 	mov	ah, WRITE_FAULT
  6014 00002460 A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  6015 00002462 7514                <1> 	jnz	short CKST_EXIT
  6016 00002464 B4AA                <1> 	mov	ah, NOT_RDY
  6017 00002466 A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  6018 00002468 740E                <1> 	jz	short CKST_EXIT
  6019 0000246A B440                <1> 	mov	ah, BAD_SEEK
  6020 0000246C A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  6021 0000246E 7408                <1> 	jz	short CKST_EXIT
  6022 00002470 B411                <1> 	mov	ah, DATA_CORRECTED
  6023 00002472 A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  6024 00002474 7502                <1> 	jnz	short CKST_EXIT
  6025                              <1> 	;mov	ah, 0
  6026 00002476 30E4                <1> 	xor	ah, ah ; 0
  6027                              <1> CKST_EXIT:
  6028 00002478 8825[DB620000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  6029 0000247E 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  6030 00002481 7402                <1> 	je	short CKST_EX1
  6031                              <1> 	;cmp	ah, 0
  6032 00002483 20E4                <1> 	and	ah, ah
  6033                              <1> CKST_EX1:
  6034 00002485 C3                  <1> 	retn
  6035                              <1> 
  6036                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6037                              <1> 
  6038                              <1> ;----------------------------------------
  6039                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  6040                              <1> ;----------------------------------------
  6041                              <1> CHECK_ER:
  6042                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  6043 00002486 668B15[625D0000]    <1> 	mov	dx, [HF_PORT]		;
  6044 0000248D FEC2                <1> 	inc	dl
  6045 0000248F EC                  <1> 	in	al, dx
  6046                              <1> 	; 10/07/2022
  6047                              <1> 	;mov	[HF_ERROR], al
  6048                              <1> 	;push	ebx	; 21/02/2015
  6049 00002490 29C9                <1> 	sub	ecx, ecx
  6050                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  6051 00002492 B108                <1> 	mov	cl, 8
  6052                              <1> CK1:	
  6053 00002494 D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  6054 00002496 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  6055 00002498 E2FA                <1> 	loop	CK1			; KEEP TRYING
  6056                              <1> CK2:
  6057                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  6058                              <1> 	;add	ebx, ecx		; ERROR CODE
  6059 0000249A 81C1[585D0000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  6060                              <1> 
  6061                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  6062                              <1> 	;;mov	ah, [bx]
  6063                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  6064 000024A0 8A21                <1> 	mov	ah, [ecx]	
  6065                              <1> CKEX:
  6066 000024A2 8825[DB620000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  6067                              <1> 	; 10/07/2022
  6068                              <1> 	;pop	ebx
  6069                              <1> 	;;cmp	ah, 0
  6070                              <1> 	;and	ah, ah
  6071 000024A8 C3                  <1> 	retn
  6072                              <1> 
  6073                              <1> ;--------------------------------------------------------
  6074                              <1> ; CHECK_DMA						:
  6075                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  6076                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  6077                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  6078                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  6079                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  6080                              <1> ;  -ERROR OTHERWISE					:
  6081                              <1> ;--------------------------------------------------------
  6082                              <1> 
  6083                              <1> 	; 11/07/2022
  6084                              <1> 	; (not needed for hard disks and 32 bit OS)
  6085                              <1> 	;
  6086                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6087                              <1> ;CHECK_DMA:
  6088                              <1> ;	;;push	ax			; SAVE REGISTERS
  6089                              <1> ;	;; 24/12/2021
  6090                              <1> ;	;;push	eax
  6091                              <1> ;	;mov	ax, 8000h		; AH = MAX # SECTORS
  6092                              <1> ;					; AL = MAX OFFSET
  6093                              <1> ;	; 10/07/2022
  6094                              <1> ;	;test	byte [CMD_BLOCK+6], ECC_MODE
  6095                              <1> ;	;jz	short CKD1
  6096                              <1> ;	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  6097                              <1> ;CKD1:	
  6098                              <1> ;	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  6099                              <1> ;	;ja	short CKDOK		; IT WILL FIT
  6100                              <1> ;	;jb	short CKDERR		; TOO MANY
  6101                              <1> ;	
  6102                              <1> ;	cmp	byte [CMD_BLOCK+1], 80h
  6103                              <1> ;	jb	short CKDOK
  6104                              <1> ;	ja	short CKDERR
  6105                              <1> ;	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  6106                              <1> ;	;jb	short CKDERR		; ERROR
  6107                              <1> ;CKD2:
  6108                              <1> ;	or	bl, bl
  6109                              <1> ;	jz	short CKDR
  6110                              <1> ;	
  6111                              <1> ;;CKDOK:	
  6112                              <1> ;	;clc				; CLEAR CARRY
  6113                              <1> ;	;;pop	ax
  6114                              <1> ;	;; 24/12/2021
  6115                              <1> ;	;pop	eax
  6116                              <1> ;	;retn				; NORMAL RETURN
  6117                              <1> ;CKDERR: 
  6118                              <1> ;	stc				; INDICATE ERROR
  6119                              <1> ;	mov	byte [DISK_STATUS1], DMA_BOUNDARY
  6120                              <1> ;	;;pop	ax
  6121                              <1> ;	;; 24/12/2021
  6122                              <1> ;	;pop	eax	
  6123                              <1> ;	retn
  6124                              <1> ;
  6125                              <1> ;	; 10/07/2022
  6126                              <1> ;CKDOK:
  6127                              <1> ;	clc
  6128                              <1> ;CKDR:
  6129                              <1> ;	retn
  6130                              <1> 
  6131                              <1> ;----------------------------------------
  6132                              <1> ;	SET UP EBX-> DISK PARMS	        :
  6133                              <1> ;----------------------------------------
  6134                              <1> 					
  6135                              <1> ; INPUT -> DL = 0 based drive number
  6136                              <1> ; OUTPUT -> EBX = disk parameter table address
  6137                              <1> 
  6138                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6139                              <1> 
  6140                              <1> GET_VEC:
  6141                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  6142                              <1> 	;mov	es, ax
  6143                              <1> 	;test	dl, 1
  6144                              <1> 	;jz	short GV_0
  6145                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  6146                              <1> ;	jmp	short GV_EXIT
  6147                              <1> ;GV_0:
  6148                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  6149                              <1> ;
  6150 000024A9 31DB                <1> 	xor	ebx, ebx
  6151 000024AB 88D3                <1> 	mov	bl, dl
  6152                              <1> 	;02/01/2015
  6153                              <1> 	;xor	bh, bh
  6154                              <1> 	;shl	bl, 1			; port address offset
  6155                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  6156                              <1> 	;shl	bl, 1			; dpt pointer offset
  6157 000024AD C0E302              <1> 	shl	bl, 2
  6158                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  6159 000024B0 81C3[E0620000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  6160                              <1> 	;push	word [bx+2]		; dpt segment
  6161                              <1> 	;pop	es
  6162                              <1> 	;mov	bx, [bx]		; dpt offset
  6163 000024B6 8B1B                <1> 	mov	ebx, [ebx]		
  6164                              <1> ;GV_EXIT:
  6165 000024B8 C3                  <1> 	retn
  6166                              <1> 
  6167                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6168                              <1> hdc1_int: ; 21/02/2015
  6169                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  6170                              <1> ;								:
  6171                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6172                              <1> ;								:
  6173                              <1> ;----------------------------------------------------------------
  6174                              <1> 
  6175                              <1> ; 22/12/2014
  6176                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  6177                              <1> ;	 '11/15/85'
  6178                              <1> ; AWARD BIOS 1999 (D1A0622) 
  6179                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  6180                              <1> 
  6181                              <1> ;int_76h:
  6182                              <1> HD_INT:
  6183                              <1> 	;push	ax
  6184                              <1> 	; 24/12/2021
  6185 000024B9 50                  <1> 	push	eax
  6186 000024BA 1E                  <1> 	push	ds
  6187                              <1> 	;CALL	DDS
  6188                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6189 000024BB 66B81000            <1> 	mov	ax, KDATA
  6190 000024BF 8ED8                <1> 	mov 	ds, ax
  6191                              <1> 	;
  6192                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  6193                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  6194 000024C1 C605[D6620000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  6195                              <1> 	;
  6196                              <1> 	;push	dx
  6197                              <1> 	; 24/12/2021
  6198 000024C8 52                  <1> 	push	edx
  6199 000024C9 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  6200                              <1> 					; Clear Controller
  6201                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  6202 000024CD EC                  <1> 	in	al, dx			;
  6203                              <1> 	;pop	dx
  6204                              <1> 	; 24/12/2021
  6205 000024CE 5A                  <1> 	pop	edx
  6206                              <1> 	NEWIODELAY
  2133 000024CF E6EB                <2>  out 0EBh,al
  6207                              <1> 	;
  6208 000024D1 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  6209 000024D3 E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  6210                              <1> 	;JMP	$+2			; WAIT
  6211                              <1> 	NEWIODELAY
  2133 000024D5 E6EB                <2>  out 0EBh,al
  6212 000024D7 E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  6213 000024D9 1F                  <1> 	pop	ds
  6214                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  6215                              <1> 	;mov	ax, 9100h		; DEVICE POST
  6216                              <1> 	;int	15h			; INTERRUPT
  6217                              <1> irq15_iret: ; 25/02/2015
  6218                              <1> 	;pop	ax
  6219                              <1> 	; 24/12/2021
  6220 000024DA 58                  <1> 	pop	eax
  6221 000024DB CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  6222                              <1> 
  6223                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6224                              <1> hdc2_int: ; 21/02/2015
  6225                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  6226                              <1> ;								:
  6227                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6228                              <1> ;								:
  6229                              <1> ;----------------------------------------------------------------
  6230                              <1> 
  6231                              <1> ;int_77h:
  6232                              <1> HD1_INT:
  6233                              <1> 	;push	ax
  6234                              <1> 	; 24/12/2021
  6235 000024DC 50                  <1> 	push	eax
  6236                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  6237                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  6238 000024DD B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  6239 000024DF E6A0                <1> 	out	0A0h, al
  6240 000024E1 EB00                <1>         jmp short $+2
  6241 000024E3 EB00                <1> 	jmp short $+2
  6242 000024E5 E4A0                <1> 	in	al, 0A0h
  6243 000024E7 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  6244 000024E9 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  6245                              <1> 	;
  6246 000024EB 1E                  <1> 	push	ds
  6247                              <1> 	;CALL	DDS
  6248                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6249 000024EC 66B81000            <1> 	mov	ax, KDATA
  6250 000024F0 8ED8                <1> 	mov 	ds, ax
  6251                              <1> 	;
  6252                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  6253                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  6254 000024F2 800D[D6620000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  6255                              <1> 	;
  6256                              <1> 	;push	dx
  6257                              <1> 	; 24/12/2021
  6258 000024F9 52                  <1> 	push	edx
  6259 000024FA 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6260                              <1> 					; Clear Controller (Award BIOS 1999)
  6261 000024FE EBCD                <1> 	jmp	short Clear_IRQ1415
  6262                              <1> 
  6263                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6264                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6265                              <1> 
  6266                              <1> ;////////////////////////////////////////////////////////////////////
  6267                              <1> ;; END OF DISK I/O SYTEM ///
  2047                                  %include 'memory.inc'  ; 09/03/2015
  2048                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2049                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.18) - MEMORY.INC
  2050                              <1> ; Last Modification: 03/02/2022 [ 31/12/2021 (Retro UNIX 386 v1.1) ]
  2051                              <1> ;
  2052                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2053                              <1> 
  2054                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.1 - MEMORY.INC (31/12/2021)
  2055                              <1> 
  2056                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2057                              <1> 
  2058                              <1> ;;04/11/2014 (unix386.s)	
  2059                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2060                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2061                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2062                              <1> ;;
  2063                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2064                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2065                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2066                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2067                              <1> 
  2068                              <1> ; 27/04/2015
  2069                              <1> ; 09/03/2015
  2070                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2071                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2072                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2073                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2074                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2075                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2076                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2077                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2078                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2079                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2080                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2081                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2082                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2083                              <1> SWP_DISK_READ_ERR 	   equ 40
  2084                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2085                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2086                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2087                              <1> SWP_DISK_WRITE_ERR         equ 44
  2088                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2089                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2090                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2091                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2092                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2093                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2094                              <1> 					; (Indicates that the page is not allocated
  2095                              <1> 					; for the process, it is a shared or system
  2096                              <1>                                         ; page, it must not be deallocated!)
  2097                              <1> ; 14/12/2020
  2098                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2099                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2100                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2101                              <1> 				; (Out of memory allocation table)	
  2102                              <1> ;
  2103                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2104                              <1> ;;
  2105                              <1> ;; 10/10/2014
  2106                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2107                              <1> ;;
  2108                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2109                              <1> ;;	(virtual address = physical address)
  2110                              <1> ;; KERNEL PAGE TABLES:
  2111                              <1> ;;	Kernel page directory and all page tables are
  2112                              <1> ;;	on memory as initialized, as equal to physical memory
  2113                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2114                              <1> ;;
  2115                              <1> ;;	what for: User pages may be swapped out, when accessing
  2116                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2117                              <1> ;;	kernel would have to swap it in! But it is also may be
  2118                              <1> ;;	in use by a user process. (In system/kernel mode
  2119                              <1> ;;	kernel can access all memory pages even if they are
  2120                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2121                              <1> ;;	cause conflicts.) 
  2122                              <1> ;;	
  2123                              <1> ;;	As result of these conditions,
  2124                              <1> ;;	all kernel pages must be initialized as equal to 
  2125                              <1> ;;	physical layout for preventing page faults. 
  2126                              <1> ;;	Also, calling "allocate page" procedure after
  2127                              <1> ;;	a page fault can cause another page fault (double fault)
  2128                              <1> ;;	if all kernel page tables would not be initialized.
  2129                              <1> ;;
  2130                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2131                              <1> ;;	memory allocation table. (double word aligned)
  2132                              <1> ;;
  2133                              <1> ;;	[next_page] = first/next free space to be searched
  2134                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2135                              <1> ;;
  2136                              <1> ;;	[last_page] = End of memory (users space), as offset
  2137                              <1> ;;	to memory allocation table. (double word aligned)
  2138                              <1> ;;
  2139                              <1> ;; USER PAGE TABLES:
  2140                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2141                              <1> ;;		'ready only' marked copies of the 
  2142                              <1> ;;		parent process's page table entries (for
  2143                              <1> ;;		same physical memory).
  2144                              <1> ;;		(A page will be copied to a new page after
  2145                              <1> ;;		 if it causes R/W page fault.)
  2146                              <1> ;;
  2147                              <1> ;;	Every user process has own (different)
  2148                              <1> ;;	page directory and page tables.	
  2149                              <1> ;;
  2150                              <1> ;;	Code starts at virtual address 0, always.
  2151                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2152                              <1> ;;	(Programs can be written/developed as simple
  2153                              <1> ;;	 flat memory programs.)
  2154                              <1> ;;
  2155                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2156                              <1> ;;	Memory page will be allocated by kernel only 
  2157                              <1> ;;		(in kernel/system mode only).
  2158                              <1> ;;	* After a
  2159                              <1> ;;	  - 'not present' page fault
  2160                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2161                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2162                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2163                              <1> ;;	  request by running process.
  2164                              <1> ;;	* While creating a process, allocating a new buffer,
  2165                              <1> ;;	  new page tables etc.
  2166                              <1> ;;
  2167                              <1> ;;	At first,
  2168                              <1> ;;	- 'allocate page' procedure will be called;
  2169                              <1> ;,	   if it will return with a valid (>0) physical address
  2170                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2171                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2172                              <1> ;;	- 'allocate page' will be called for allocating page
  2173                              <1> ;;	   directory, page table and running space (data/code).
  2174                              <1> ;;	- every successful 'allocate page' call will decrease
  2175                              <1> ;;	  'free_pages' count (pointer).
  2176                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2177                              <1> ;;	  if 'free_pages' points to a ZERO.
  2178                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2179                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2180                              <1> ;;	  error except errors caused by attribute conflicts.
  2181                              <1> ;;	 (swapper functions)	 
  2182                              <1> ;;					
  2183                              <1> ;;	At second,
  2184                              <1> ;;	- page directory entry will be updated then page table
  2185                              <1> ;;	  entry will be updated.		
  2186                              <1> ;;
  2187                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2188                              <1> ;;	- M.A.T. has a size according to available memory as
  2189                              <1> ;;	  follows:
  2190                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2191                              <1> ;;		  - a bit with value of 0 means allocated page
  2192                              <1> ;;		  - a bit with value of 1 means a free page
  2193                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2194                              <1> ;;	  depending on M.A.T.
  2195                              <1> ;;		(NOTE: Free page count will not be checked
  2196                              <1> ;;		again -on M.A.T.- after initialization. 
  2197                              <1> ;;		Kernel will trust on initial count.)
  2198                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2199                              <1> ;;	  and it will be increased by deallocation procedures.
  2200                              <1> ;;	
  2201                              <1> ;;	- Available memory will be calculated during
  2202                              <1> ;;	  the kernel's initialization stage (in real mode).
  2203                              <1> ;;	  Memory allocation table and kernel page tables 
  2204                              <1> ;;	  will be formatted/sized as result of available
  2205                              <1> ;;	  memory calculation before paging is enabled.
  2206                              <1> ;;
  2207                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2208                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2209                              <1> ;;	- Memory allocation for kernel page directory size 
  2210                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2211                              <1> ;;	  for page tables)
  2212                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2213                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2214                              <1> ;;	- User (available) space will be started 
  2215                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2216                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2217                              <1> ;;	  memory allocation table and kernel's page directory
  2218                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2219                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2220                              <1> ;; 	  for buffers.
  2221                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2222                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2223                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2224                              <1> ;;
  2225                              <1> ;; For 1GB Available Memory:
  2226                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2227                              <1> ;;	- Memory allocation for kernel page directory size 
  2228                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2229                              <1> ;;	  for page tables)
  2230                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2231                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2232                              <1> ;;	- User (available) space will be started 
  2233                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2234                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2235                              <1> ;;	  memory allocation table and kernel's page directory
  2236                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2237                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2238                              <1> ;; 	  for buffers.
  2239                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2240                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2241                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2242                              <1> ;;
  2243                              <1> ;;
  2244                              <1> 
  2245                              <1> ;;************************************************************************************
  2246                              <1> ;; 
  2247                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2248                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2249                              <1> 
  2250                              <1> ;; Main factor: "sys fork" system call 
  2251                              <1> ;;	
  2252                              <1> ;; 		FORK
  2253                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2254                              <1> ;;  writable pages ---->|
  2255                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2256                              <1> ;; 
  2257                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2258                              <1> ;; 
  2259                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2260                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2261                              <1> ;;       -while R/W bit is 0-. 
  2262                              <1> ;; 
  2263                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2264                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2265                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2266                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2267                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2268                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2269                              <1> ;; 
  2270                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2271                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2272                              <1> ;;   Parent's PTE attributes are not changed.
  2273                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2274                              <1> ;;    destroy/mix previous fork result).
  2275                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2276                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2277                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2278                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2279                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2280                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2281                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2282                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2283                              <1> ;; 
  2284                              <1> ;; !? WHAT FOR (duplication after duplication):
  2285                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2286                              <1> ;; program/executable code continues from specified location as child process, 
  2287                              <1> ;; returns back previous code location as parent process, every child after 
  2288                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2289                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2290                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2291                              <1> ;; was copied to child's process segment (all of code and data) according to
  2292                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2293                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2294                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2295                              <1> ;; (complete running image of parent process) to the child process; 
  2296                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2297                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2298                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2299                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2300                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2301                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2302                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2303                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2304                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2305                              <1> ;; for sharing same read only pages between parent and child processes.
  2306                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2307                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2308                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2309                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2310                              <1> ;; -deallocation problem-.
  2311                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2312                              <1> ;; 
  2313                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2314                              <1> ;; # Page fault handler will do those:
  2315                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2316                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2317                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2318                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2319                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2320                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2321                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2322                              <1> ;;     to child process.)	
  2323                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2324                              <1> ;; # Page fault handler will do those:
  2325                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2326                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2327                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2328                              <1> ;;     address or not. 
  2329                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2330                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2331                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2332                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2333                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2334                              <1> ;; 
  2335                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2336                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2337                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2338                              <1> ;;       duplication method details, it is not possible multiple child processes
  2339                              <1> ;;       were using same page with duplicated PTEs.
  2340                              <1> ;; 
  2341                              <1> ;;************************************************************************************   
  2342                              <1> 
  2343                              <1> ;; 08/10/2014
  2344                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2345                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2346                              <1> 
  2347                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2348                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2349                              <1> ;; (25/08/2014, Revision: 5057) file 
  2350                              <1> ;; by KolibriOS Team (2004-2012)
  2351                              <1> 
  2352                              <1> allocate_page:
  2353                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2354                              <1> 	; 01/07/2015
  2355                              <1> 	; 05/05/2015
  2356                              <1> 	; 30/04/2015
  2357                              <1> 	; 16/10/2014
  2358                              <1> 	; 08/10/2014
  2359                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2360                              <1> 	;
  2361                              <1> 	; INPUT -> none
  2362                              <1> 	;
  2363                              <1> 	; OUTPUT ->
  2364                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2365                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2366                              <1> 	;
  2367                              <1> 	;	CF = 1 and EAX = 0 
  2368                              <1> 	; 		   if there is not a free page to be allocated	
  2369                              <1> 	;
  2370                              <1> 	; Modified Registers -> none (except EAX)
  2371                              <1> 	;
  2372 00002500 A1[50620000]        <1> 	mov	eax, [free_pages]
  2373 00002505 21C0                <1> 	and	eax, eax
  2374 00002507 7438                <1> 	jz	short out_of_memory
  2375                              <1> 	;
  2376 00002509 53                  <1> 	push	ebx
  2377 0000250A 51                  <1> 	push	ecx
  2378                              <1> 	;
  2379 0000250B BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2380 00002510 89D9                <1> 	mov	ecx, ebx
  2381                              <1>  				     ; NOTE: 32 (first_page) is initial
  2382                              <1> 				     ; value of [next_page].
  2383                              <1> 				     ; It points to the first available
  2384                              <1> 				     ; page block for users (ring 3) ...	
  2385                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2386                              <1> 				     ; (at the of the first 4 MB)		
  2387 00002512 031D[54620000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2388                              <1> 				 ; next_free_page >> 5
  2389 00002518 030D[58620000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2390                              <1> 				 ; (total_pages - 1) >> 5
  2391                              <1> al_p_scan:
  2392 0000251E 39CB                <1> 	cmp	ebx, ecx
  2393 00002520 770A                <1> 	ja	short al_p_notfound
  2394                              <1> 	;
  2395                              <1> 	; 01/07/2015
  2396                              <1> 	; AMD64 Architecture Programmers Manual
  2397                              <1> 	; Volume 3:
  2398                              <1> 	; General-Purpose and System Instructions
  2399                              <1> 	;
  2400                              <1> 	; BSF - Bit Scan Forward
  2401                              <1> 	;
  2402                              <1> 	;   Searches the value in a register or a memory location
  2403                              <1> 	;   (second operand) for the least-significant set bit. 
  2404                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2405                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2406                              <1> 	;   register (first operand). If the second operand contains 0, 
  2407                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2408                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2409                              <1> 	;   of the searched value
  2410                              <1> 	;
  2411 00002522 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2412                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2413                              <1> 			   ; loads the destination with an index to
  2414                              <1> 			   ; first set bit. (0 -> 31) 
  2415                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2416 00002525 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2417                              <1> 			 ;
  2418                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2419                              <1> 			 ;	  with value of 1 means 
  2420                              <1> 			 ;	  the corresponding page is free 
  2421                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2422 00002527 83C304              <1> 	add	ebx, 4
  2423                              <1> 			 ; We return back for searching next page block
  2424                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2425                              <1> 			 ;	 we always will find at least 1 free page here.
  2426 0000252A EBF2                <1>         jmp     short al_p_scan
  2427                              <1> 	;
  2428                              <1> al_p_notfound:
  2429 0000252C 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2430 00002532 890D[54620000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2431                              <1> 				 ; (deallocate_page procedure will change it)
  2432 00002538 31C0                <1> 	xor	eax, eax
  2433 0000253A A3[50620000]        <1> 	mov	[free_pages], eax ; 0
  2434 0000253F 59                  <1> 	pop	ecx
  2435 00002540 5B                  <1> 	pop	ebx
  2436                              <1> 	;
  2437                              <1> ; 24/12/2021
  2438                              <1> ; ('swap_out' procedure call is disabled)
  2439                              <1> 
  2440                              <1> out_of_memory:
  2441                              <1> ;	call	swap_out
  2442                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2443                              <1> ;	;
  2444                              <1> ;	sub 	eax, eax ; 0
  2445 00002541 F9                  <1> 	stc
  2446 00002542 C3                  <1> 	retn
  2447                              <1> 
  2448                              <1> al_p_found:
  2449 00002543 89D9                <1> 	mov	ecx, ebx
  2450 00002545 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2451 0000254B 890D[54620000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2452                              <1> 				 ; address/offset (to the next)
  2453 00002551 FF0D[50620000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2454                              <1> 	;
  2455 00002557 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2456                              <1> 				 ; is copied into the Carry Flag and then cleared
  2457                              <1> 				 ; in the destination.
  2458                              <1> 				 ;
  2459                              <1> 				 ; Reset the bit which is corresponding to the 
  2460                              <1> 				 ; (just) allocated page.
  2461                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2462 0000255A C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2463 0000255D 01C8                <1> 	add	eax, ecx	 ; = page number
  2464 0000255F C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2465                              <1> 	; EAX = physical address of memory page
  2466                              <1> 	;
  2467                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2468                              <1> 	;       according to this EAX value...
  2469 00002562 59                  <1> 	pop	ecx
  2470 00002563 5B                  <1> 	pop	ebx
  2471                              <1> al_p_ok:
  2472 00002564 C3                  <1> 	retn
  2473                              <1> 
  2474                              <1> make_page_dir:
  2475                              <1> 	; 18/04/2015
  2476                              <1> 	; 12/04/2015
  2477                              <1> 	; 23/10/2014
  2478                              <1> 	; 16/10/2014
  2479                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2480                              <1> 	;
  2481                              <1> 	; INPUT ->
  2482                              <1> 	;	none
  2483                              <1> 	; OUTPUT ->
  2484                              <1> 	;	(EAX = 0)
  2485                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2486                              <1> 	;	cf = 0 ->
  2487                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2488                              <1> 	;		  process/user.
  2489                              <1> 	;
  2490                              <1> 	; Modified Registers -> EAX
  2491                              <1> 	;
  2492 00002565 E896FFFFFF          <1> 	call	allocate_page
  2493 0000256A 7216                <1> 	jc	short mkpd_error
  2494                              <1> 	;
  2495 0000256C A3[63660000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2496                              <1> 				  ; (Physical address)
  2497                              <1> clear_page:
  2498                              <1> 	; 18/04/2015
  2499                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2500                              <1> 	;
  2501                              <1> 	; INPUT ->
  2502                              <1> 	;	EAX = physical address of the page
  2503                              <1> 	; OUTPUT ->
  2504                              <1> 	;	all bytes of the page will be cleared
  2505                              <1> 	;
  2506                              <1> 	; Modified Registers -> none
  2507                              <1> 	;
  2508 00002571 57                  <1> 	push	edi
  2509 00002572 51                  <1> 	push	ecx
  2510 00002573 50                  <1> 	push	eax
  2511 00002574 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2512 00002579 89C7                <1> 	mov	edi, eax
  2513 0000257B 31C0                <1> 	xor	eax, eax
  2514 0000257D F3AB                <1> 	rep	stosd
  2515 0000257F 58                  <1> 	pop	eax
  2516 00002580 59                  <1> 	pop	ecx
  2517 00002581 5F                  <1> 	pop	edi
  2518                              <1> mkpd_error:
  2519                              <1> mkpt_error:
  2520 00002582 C3                  <1> 	retn
  2521                              <1> 
  2522                              <1> make_page_table:
  2523                              <1> 	; 23/06/2015
  2524                              <1> 	; 18/04/2015
  2525                              <1> 	; 12/04/2015
  2526                              <1> 	; 16/10/2014
  2527                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2528                              <1> 	;
  2529                              <1> 	; INPUT ->
  2530                              <1> 	;	EBX = virtual (linear) address
  2531                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2532                              <1> 	;	      (higher 20 bits must be ZERO)
  2533                              <1> 	;	      (bit 0 must be 1)	 
  2534                              <1> 	;	u.pgdir = page directory (physical) address
  2535                              <1> 	; OUTPUT ->
  2536                              <1> 	;	EDX = Page directory entry address
  2537                              <1> 	;	EAX = Page table address
  2538                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2539                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2540                              <1> 	;
  2541                              <1> 	; Modified Registers -> EAX, EDX
  2542                              <1> 	;
  2543 00002583 E878FFFFFF          <1> 	call	allocate_page
  2544 00002588 72F8                <1> 	jc	short mkpt_error
  2545 0000258A E811000000          <1> 	call	set_pde	
  2546 0000258F EBE0                <1> 	jmp	short clear_page
  2547                              <1> 
  2548                              <1> make_page:
  2549                              <1> 	; 24/07/2015
  2550                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2551                              <1> 	;
  2552                              <1> 	; INPUT ->
  2553                              <1> 	;	EBX = virtual (linear) address
  2554                              <1> 	;	ECX = page attributes (lower 12 bits)
  2555                              <1> 	;	      (higher 20 bits must be ZERO)
  2556                              <1> 	;	      (bit 0 must be 1)	 
  2557                              <1> 	;	u.pgdir = page directory (physical) address
  2558                              <1> 	; OUTPUT ->
  2559                              <1> 	;	EBX = Virtual address
  2560                              <1> 	;	(EDX = PTE value)
  2561                              <1> 	;	EAX = Physical address
  2562                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2563                              <1> 	;
  2564                              <1> 	; Modified Registers -> EAX, EDX
  2565                              <1> 	;
  2566 00002591 E86AFFFFFF          <1> 	call	allocate_page
  2567 00002596 7207                <1> 	jc	short mkp_err
  2568 00002598 E821000000          <1> 	call	set_pte	
  2569 0000259D 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2570                              <1> mkp_err:
  2571 0000259F C3                  <1> 	retn
  2572                              <1> 
  2573                              <1> set_pde:	; Set page directory entry (PDE)
  2574                              <1> 	; 20/07/2015
  2575                              <1> 	; 18/04/2015
  2576                              <1> 	; 12/04/2015
  2577                              <1> 	; 23/10/2014
  2578                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2579                              <1> 	;
  2580                              <1> 	; INPUT ->
  2581                              <1> 	;	EAX = physical address
  2582                              <1> 	;	      (use present value if EAX = 0)
  2583                              <1> 	;	EBX = virtual (linear) address
  2584                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2585                              <1> 	;	      (higher 20 bits must be ZERO)
  2586                              <1> 	;	      (bit 0 must be 1)	 
  2587                              <1> 	;	u.pgdir = page directory (physical) address
  2588                              <1> 	; OUTPUT ->
  2589                              <1> 	;	EDX = PDE address
  2590                              <1> 	;	EAX = page table address (physical)
  2591                              <1> 	;	;(CF=1 -> Invalid page address)
  2592                              <1> 	;
  2593                              <1> 	; Modified Registers -> EDX
  2594                              <1> 	;
  2595 000025A0 89DA                <1> 	mov	edx, ebx
  2596 000025A2 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2597 000025A5 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2598 000025A8 0315[63660000]      <1> 	add	edx, [u.pgdir]
  2599                              <1> 	;
  2600 000025AE 21C0                <1> 	and	eax, eax
  2601 000025B0 7506                <1> 	jnz	short spde_1
  2602                              <1> 	;
  2603 000025B2 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2604                              <1> 	;test	al, 1
  2605                              <1> 	;jz	short spde_2
  2606 000025B4 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2607                              <1> spde_1:
  2608                              <1> 	;and	cx, 0FFFh
  2609 000025B8 8902                <1> 	mov	[edx], eax
  2610 000025BA 66090A              <1> 	or	[edx], cx
  2611 000025BD C3                  <1> 	retn
  2612                              <1> ;spde_2: ; error
  2613                              <1> ;	stc
  2614                              <1> ;	retn
  2615                              <1> 
  2616                              <1> set_pte:	; Set page table entry (PTE)
  2617                              <1> 	; 24/07/2015
  2618                              <1> 	; 20/07/2015
  2619                              <1> 	; 23/06/2015
  2620                              <1> 	; 18/04/2015
  2621                              <1> 	; 12/04/2015
  2622                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2623                              <1> 	;
  2624                              <1> 	; INPUT ->
  2625                              <1> 	;	EAX = physical page address
  2626                              <1> 	;	      (use present value if EAX = 0)
  2627                              <1> 	;	EBX = virtual (linear) address
  2628                              <1> 	;	ECX = page attributes (lower 12 bits)
  2629                              <1> 	;	      (higher 20 bits must be ZERO)
  2630                              <1> 	;	      (bit 0 must be 1)	 
  2631                              <1> 	;	u.pgdir = page directory (physical) address
  2632                              <1> 	; OUTPUT ->
  2633                              <1> 	;	EAX = physical page address
  2634                              <1> 	;	(EDX = PTE value)
  2635                              <1> 	;	EBX = virtual address
  2636                              <1> 	;
  2637                              <1> 	;	CF = 1 -> error
  2638                              <1> 	;
  2639                              <1> 	; Modified Registers -> EAX, EDX
  2640                              <1> 	;
  2641 000025BE 50                  <1> 	push	eax
  2642 000025BF A1[63660000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2643 000025C4 E837000000          <1> 	call 	get_pde
  2644                              <1> 		; EDX = PDE address
  2645                              <1> 		; EAX = PDE value
  2646 000025C9 5A                  <1> 	pop	edx ; physical page address
  2647 000025CA 722A                <1> 	jc	short spte_err ; PDE not present
  2648                              <1> 	;
  2649 000025CC 53                  <1> 	push	ebx ; 24/07/2015
  2650 000025CD 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2651                              <1> 			    ; EDX = PT address (physical)	
  2652 000025D1 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2653 000025D4 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2654                              <1> 			 ; clear higher 10 bits (PD bits)
  2655 000025DA C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2656 000025DD 01C3                <1> 	add	ebx, eax
  2657                              <1> 	;
  2658 000025DF 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2659 000025E1 A801                <1> 	test	al, 1
  2660 000025E3 740C                <1> 	jz	short spte_0
  2661 000025E5 09D2                <1> 	or	edx, edx
  2662 000025E7 750F                <1> 	jnz	short spte_1
  2663 000025E9 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2664 000025ED 89C2                <1> 	mov	edx, eax
  2665 000025EF EB09                <1> 	jmp	short spte_2	
  2666                              <1> spte_0:
  2667                              <1> 	; If this PTE contains a swap (disk) address,
  2668                              <1> 	; it can be updated by using 'swap_in' procedure
  2669                              <1> 	; only!
  2670 000025F1 21C0                <1> 	and	eax, eax
  2671 000025F3 7403                <1> 	jz	short spte_1
  2672                              <1> 	; 24/07/2015
  2673                              <1> 	; swapped page ! (on disk)
  2674 000025F5 5B                  <1> 	pop	ebx
  2675                              <1> spte_err:
  2676 000025F6 F9                  <1> 	stc
  2677 000025F7 C3                  <1> 	retn
  2678                              <1> spte_1: 
  2679 000025F8 89D0                <1> 	mov	eax, edx
  2680                              <1> spte_2:
  2681 000025FA 09CA                <1> 	or	edx, ecx
  2682                              <1> 	; 23/06/2015
  2683 000025FC 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2684                              <1> 	; 24/07/2015
  2685 000025FE 5B                  <1> 	pop	ebx
  2686 000025FF C3                  <1> 	retn
  2687                              <1> 
  2688                              <1> get_pde:	; Get present value of the relevant PDE
  2689                              <1> 	; 20/07/2015
  2690                              <1> 	; 18/04/2015
  2691                              <1> 	; 12/04/2015
  2692                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2693                              <1> 	;
  2694                              <1> 	; INPUT ->
  2695                              <1> 	;	EBX = virtual (linear) address
  2696                              <1> 	;	EAX = page directory (physical) address
  2697                              <1> 	; OUTPUT ->
  2698                              <1> 	;	EDX = Page directory entry address
  2699                              <1> 	;	EAX = Page directory entry value
  2700                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2701                              <1> 	; Modified Registers -> EDX, EAX
  2702                              <1> 	;
  2703 00002600 89DA                <1> 	mov	edx, ebx
  2704 00002602 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2705 00002605 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2706 00002608 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2707 0000260A 8B02                <1> 	mov	eax, [edx]
  2708 0000260C A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2709 0000260E 751F                <1> 	jnz	short gpte_retn
  2710 00002610 F9                  <1> 	stc
  2711                              <1> gpde_retn:	
  2712 00002611 C3                  <1> 	retn
  2713                              <1> 
  2714                              <1> get_pte:
  2715                              <1> 		; Get present value of the relevant PTE
  2716                              <1> 	; 29/07/2015
  2717                              <1> 	; 20/07/2015
  2718                              <1> 	; 18/04/2015
  2719                              <1> 	; 12/04/2015
  2720                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2721                              <1> 	;
  2722                              <1> 	; INPUT ->
  2723                              <1> 	;	EBX = virtual (linear) address
  2724                              <1> 	;	EAX = page directory (physical) address
  2725                              <1> 	; OUTPUT ->
  2726                              <1> 	;	EDX = Page table entry address (if CF=0)
  2727                              <1> 	;	      Page directory entry address (if CF=1)
  2728                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2729                              <1> 	;	EAX = Page table entry value (page address)
  2730                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2731                              <1> 	; Modified Registers -> EAX, EDX
  2732                              <1> 	;
  2733 00002612 E8E9FFFFFF          <1> 	call 	get_pde
  2734 00002617 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2735                              <1> 	;jnc	short gpte_1
  2736                              <1> 	;retn
  2737                              <1> ;gpte_1:
  2738 00002619 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2739 0000261D 89DA                <1> 	mov	edx, ebx
  2740 0000261F C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2741 00002622 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2742                              <1> 			 ; clear higher 10 bits (PD bits)
  2743 00002628 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2744 0000262B 01C2                <1> 	add	edx, eax
  2745 0000262D 8B02                <1> 	mov	eax, [edx]
  2746                              <1> gpte_retn:
  2747 0000262F C3                  <1> 	retn
  2748                              <1> 
  2749                              <1> deallocate_page_dir:
  2750                              <1> 	; 15/09/2015
  2751                              <1> 	; 05/08/2015
  2752                              <1> 	; 30/04/2015
  2753                              <1> 	; 28/04/2015
  2754                              <1> 	; 17/10/2014
  2755                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2756                              <1> 	;
  2757                              <1> 	; INPUT ->
  2758                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2759                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2760                              <1> 	; OUTPUT ->
  2761                              <1> 	;	All of page tables in the page directory
  2762                              <1> 	;	and page dir's itself will be deallocated
  2763                              <1> 	;	except 'read only' duplicated pages (will be converted
  2764                              <1> 	;	to writable pages).
  2765                              <1> 	;
  2766                              <1> 	; Modified Registers -> EAX
  2767                              <1> 	;
  2768                              <1> 	;
  2769 00002630 56                  <1> 	push	esi
  2770 00002631 51                  <1> 	push	ecx
  2771 00002632 50                  <1> 	push	eax
  2772 00002633 89C6                <1> 	mov	esi, eax 
  2773 00002635 31C9                <1> 	xor	ecx, ecx
  2774                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2775                              <1> 	; it must not be deallocated
  2776 00002637 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2777                              <1> dapd_0:
  2778 00002639 AD                  <1> 	lodsd
  2779 0000263A A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2780 0000263C 7409                <1> 	jz	short dapd_1	
  2781 0000263E 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2782 00002642 E812000000          <1> 	call	deallocate_page_table			
  2783                              <1> dapd_1:
  2784 00002647 41                  <1> 	inc	ecx ; page directory entry index
  2785 00002648 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2786 0000264E 72E9                <1> 	jb	short dapd_0
  2787                              <1> dapd_2:
  2788 00002650 58                  <1> 	pop	eax
  2789 00002651 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2790 00002656 59                  <1> 	pop	ecx
  2791 00002657 5E                  <1> 	pop	esi
  2792 00002658 C3                  <1> 	retn
  2793                              <1> 
  2794                              <1> deallocate_page_table:
  2795                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2796                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2797                              <1> 	; 19/09/2015
  2798                              <1> 	; 15/09/2015
  2799                              <1> 	; 05/08/2015
  2800                              <1> 	; 30/04/2015
  2801                              <1> 	; 28/04/2015
  2802                              <1> 	; 24/10/2014
  2803                              <1> 	; 23/10/2014
  2804                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2805                              <1> 	;
  2806                              <1> 	; INPUT ->
  2807                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2808                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2809                              <1> 	;	(ECX = page directory entry index)
  2810                              <1> 	; OUTPUT ->
  2811                              <1> 	;	All of pages in the page table and page table's itself
  2812                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2813                              <1> 	;	(will be converted to writable pages).
  2814                              <1> 	;
  2815                              <1> 	; Modified Registers -> EAX
  2816                              <1> 	;
  2817 00002659 56                  <1> 	push	esi
  2818 0000265A 57                  <1> 	push	edi
  2819 0000265B 52                  <1> 	push	edx
  2820 0000265C 50                  <1> 	push	eax ; *
  2821 0000265D 89C6                <1> 	mov	esi, eax 
  2822 0000265F 31FF                <1> 	xor	edi, edi ; 0
  2823                              <1> dapt_0:
  2824 00002661 AD                  <1> 	lodsd
  2825 00002662 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2826 00002664 7455                <1> 	jz	short dapt_1
  2827                              <1> 	;
  2828 00002666 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2829                              <1> 				  ; (must be 1)
  2830 00002668 753F                <1> 	jnz	short dapt_3
  2831                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2832 0000266A 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2833                              <1> 				   ; as child's page ?
  2834 0000266E 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2835                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2836                              <1> 	; ECX = page directory entry index (0-1023)
  2837 00002670 53                  <1> 	push	ebx
  2838 00002671 51                  <1> 	push	ecx
  2839 00002672 66C1E102            <1> 	shl	cx, 2 ; *4 
  2840 00002676 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2841 00002678 8B0B                <1> 	mov	ecx, [ebx]
  2842 0000267A F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2843 0000267D 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2844 0000267F 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2845                              <1> 	; EDI = page table entry index (0-1023)
  2846 00002684 89FA                <1> 	mov	edx, edi 
  2847 00002686 66C1E202            <1> 	shl	dx, 2 ; *4 
  2848 0000268A 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2849 0000268C 8B1A                <1> 	mov	ebx, [edx]
  2850 0000268E F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2851 00002691 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2852 00002693 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2853 00002697 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2854 0000269C 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2855 0000269E 7507                <1> 	jne	short dapt_2	; not same page
  2856                              <1> 				; deallocate the child's page
  2857 000026A0 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2858 000026A3 59                  <1> 	pop	ecx
  2859 000026A4 5B                  <1> 	pop	ebx
  2860 000026A5 EB0D                <1> 	jmp	short dapt_4
  2861                              <1> 
  2862                              <1> ; 24/12/2021
  2863                              <1> ; ('dapt_1' is disabled)
  2864                              <1> ;
  2865                              <1> ;dapt_1:
  2866                              <1> ;	or	eax, eax	; swapped page ?
  2867                              <1> ;	jz	short dapt_5	; no
  2868                              <1> ;				; yes
  2869                              <1> ;	shr	eax, 1
  2870                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2871                              <1> ;				  ; on the swap disk (or in file)
  2872                              <1> ;	jmp	short dapt_5
  2873                              <1> dapt_2:
  2874 000026A7 59                  <1> 	pop	ecx
  2875 000026A8 5B                  <1> 	pop	ebx
  2876                              <1> dapt_3:	
  2877                              <1> 	; 12/07/2016
  2878 000026A9 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2879 000026AD 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2880                              <1> 	;
  2881                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2882 000026AF E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2883                              <1> dapt_4:
  2884 000026B4 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2885                              <1> dapt_1:	; 24/12/2021
  2886                              <1> dapt_5:
  2887 000026BB 47                  <1> 	inc	edi ; page table entry index
  2888 000026BC 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2889 000026C2 729D                <1> 	jb	short dapt_0
  2890                              <1> 	;
  2891 000026C4 58                  <1> 	pop	eax ; *
  2892 000026C5 5A                  <1> 	pop	edx
  2893 000026C6 5F                  <1> 	pop	edi	
  2894 000026C7 5E                  <1> 	pop	esi
  2895                              <1> 	;
  2896                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2897                              <1> 	;retn
  2898                              <1> 
  2899                              <1> deallocate_page:
  2900                              <1> 	; 15/09/2015
  2901                              <1> 	; 28/04/2015
  2902                              <1> 	; 10/03/2015
  2903                              <1> 	; 17/10/2014
  2904                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2905                              <1> 	;
  2906                              <1> 	; INPUT -> 
  2907                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2908                              <1> 	; OUTPUT ->
  2909                              <1> 	;	[free_pages] is increased
  2910                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2911                              <1> 	;	CF = 1 if the page is already deallocated
  2912                              <1> 	; 	       (or not allocated) before.  
  2913                              <1> 	;
  2914                              <1> 	; Modified Registers -> EAX
  2915                              <1> 	;
  2916 000026C8 53                  <1> 	push	ebx
  2917 000026C9 52                  <1> 	push	edx
  2918                              <1> 	;
  2919 000026CA C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2920                              <1> 				     ; 12 bits right
  2921                              <1> 				     ; to get page number
  2922 000026CD 89C2                <1> 	mov	edx, eax
  2923                              <1> 	; 15/09/2015
  2924 000026CF C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2925                              <1> 				     ; (1 allocation bit = 1 page)
  2926                              <1> 				     ; (1 allocation bytes = 8 pages)
  2927 000026D2 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2928                              <1> 				     ; (to get 32 bit position)			
  2929                              <1> 	;
  2930 000026D5 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2931 000026DA 01D3                <1> 	add	ebx, edx
  2932 000026DC 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2933                              <1> 				     ; (allocation bit position)	 
  2934 000026DF 3B15[54620000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2935                              <1> 				     ; than the address in 'next_page' ?
  2936                              <1> 				     ; (next/first free page value)		
  2937 000026E5 7306                <1> 	jnb	short dap_1	     ; no	
  2938 000026E7 8915[54620000]      <1> 	mov	[next_page], edx     ; yes
  2939                              <1> dap_1:
  2940 000026ED 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2941                              <1> 				     ; set relevant bit to 1.
  2942                              <1> 				     ; set CF to the previous bit value	
  2943                              <1> 	;cmc			     ; complement carry flag	
  2944                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2945                              <1> 				     ; if the page is already deallocated
  2946                              <1> 				     ; before.	
  2947 000026F0 FF05[50620000]      <1>         inc     dword [free_pages]
  2948                              <1> dap_2:
  2949 000026F6 5A                  <1> 	pop	edx
  2950 000026F7 5B                  <1> 	pop	ebx
  2951 000026F8 C3                  <1> 	retn
  2952                              <1> 
  2953                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2954                              <1> ;;                                                              ;;
  2955                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2956                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2957                              <1> ;;                                                              ;;
  2958                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2959                              <1> 
  2960                              <1> ;;$Revision: 5057 $
  2961                              <1> 
  2962                              <1> 
  2963                              <1> ;;align 4
  2964                              <1> ;;proc alloc_page
  2965                              <1> 
  2966                              <1> ;;        pushfd
  2967                              <1> ;;        cli
  2968                              <1> ;;        push    ebx
  2969                              <1> ;;;//-
  2970                              <1> ;;        cmp     [pg_data.pages_free], 1
  2971                              <1> ;;        jle     .out_of_memory
  2972                              <1> ;;;//-
  2973                              <1> ;;
  2974                              <1> ;;        mov     ebx, [page_start]
  2975                              <1> ;;        mov     ecx, [page_end]
  2976                              <1> ;;.l1:
  2977                              <1> ;;        bsf     eax, [ebx];
  2978                              <1> ;;        jnz     .found
  2979                              <1> ;;        add     ebx, 4
  2980                              <1> ;;        cmp     ebx, ecx
  2981                              <1> ;;        jb      .l1
  2982                              <1> ;;        pop     ebx
  2983                              <1> ;;        popfd
  2984                              <1> ;;        xor     eax, eax
  2985                              <1> ;;        ret
  2986                              <1> ;;.found:
  2987                              <1> ;;;//-
  2988                              <1> ;;        dec     [pg_data.pages_free]
  2989                              <1> ;;        jz      .out_of_memory
  2990                              <1> ;;;//-
  2991                              <1> ;;        btr     [ebx], eax
  2992                              <1> ;;        mov     [page_start], ebx
  2993                              <1> ;;        sub     ebx, sys_pgmap
  2994                              <1> ;;        lea     eax, [eax+ebx*8]
  2995                              <1> ;;        shl     eax, 12
  2996                              <1> ;;;//-       dec [pg_data.pages_free]
  2997                              <1> ;;        pop     ebx
  2998                              <1> ;;        popfd
  2999                              <1> ;;        ret
  3000                              <1> ;;;//-
  3001                              <1> ;;.out_of_memory:
  3002                              <1> ;;        mov     [pg_data.pages_free], 1
  3003                              <1> ;;        xor     eax, eax
  3004                              <1> ;;        pop     ebx
  3005                              <1> ;;        popfd
  3006                              <1> ;;        ret
  3007                              <1> ;;;//-
  3008                              <1> ;;endp
  3009                              <1> 
  3010                              <1> duplicate_page_dir:
  3011                              <1> 	; 21/09/2015
  3012                              <1> 	; 31/08/2015
  3013                              <1> 	; 20/07/2015
  3014                              <1> 	; 28/04/2015
  3015                              <1> 	; 27/04/2015
  3016                              <1> 	; 18/04/2015
  3017                              <1> 	; 12/04/2015
  3018                              <1> 	; 18/10/2014
  3019                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3020                              <1> 	;
  3021                              <1> 	; INPUT -> 
  3022                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3023                              <1> 	;		    page directory.
  3024                              <1> 	; OUTPUT ->
  3025                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3026                              <1> 	;	       page directory.
  3027                              <1> 	;	(New page directory with new page table entries.)
  3028                              <1> 	;	(New page tables with read only copies of the parent's
  3029                              <1> 	;	pages.)
  3030                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3031                              <1> 	;
  3032                              <1> 	; Modified Registers -> none (except EAX)
  3033                              <1> 	;
  3034 000026F9 E802FEFFFF          <1> 	call	allocate_page
  3035 000026FE 723E                <1> 	jc	short dpd_err
  3036                              <1> 	;
  3037 00002700 55                  <1> 	push	ebp ; 20/07/2015
  3038 00002701 56                  <1> 	push	esi
  3039 00002702 57                  <1> 	push	edi
  3040 00002703 53                  <1> 	push	ebx
  3041 00002704 51                  <1> 	push	ecx
  3042 00002705 8B35[63660000]      <1> 	mov	esi, [u.pgdir]
  3043 0000270B 89C7                <1> 	mov	edi, eax
  3044 0000270D 50                  <1> 	push	eax ; save child's page directory address
  3045                              <1> 	; 31/08/2015
  3046                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3047                              <1> 	; (use same system space for all user page tables) 
  3048 0000270E A5                  <1> 	movsd
  3049 0000270F BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3050 00002714 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3051                              <1> dpd_0:	
  3052 00002719 AD                  <1> 	lodsd
  3053                              <1> 	;or	eax, eax
  3054                              <1>         ;jnz     short dpd_1
  3055 0000271A A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3056 0000271C 7508                <1> 	jnz	short dpd_1
  3057                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3058 0000271E 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3059 00002724 EB0F                <1> 	jmp	short dpd_2
  3060                              <1> dpd_1:	
  3061 00002726 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3062 0000272A 89C3                <1> 	mov	ebx, eax
  3063                              <1> 	; EBX = Parent's page table address
  3064 0000272C E81F000000          <1> 	call	duplicate_page_table
  3065 00002731 720C                <1> 	jc	short dpd_p_err
  3066                              <1> 	; EAX = Child's page table address
  3067 00002733 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3068                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3069                              <1> 			 ; (present, writable, user)
  3070                              <1> dpd_2:
  3071 00002735 AB                  <1> 	stosd
  3072 00002736 E2E1                <1> 	loop	dpd_0
  3073                              <1> 	;
  3074 00002738 58                  <1> 	pop	eax  ; restore child's page directory address
  3075                              <1> dpd_3:
  3076 00002739 59                  <1> 	pop	ecx
  3077 0000273A 5B                  <1> 	pop	ebx
  3078 0000273B 5F                  <1> 	pop	edi
  3079 0000273C 5E                  <1> 	pop	esi
  3080 0000273D 5D                  <1> 	pop	ebp ; 20/07/2015
  3081                              <1> dpd_err:
  3082 0000273E C3                  <1> 	retn
  3083                              <1> dpd_p_err:
  3084                              <1> 	; release the allocated pages missing (recover free space)
  3085 0000273F 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3086 00002740 8B1D[63660000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3087 00002746 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3088 0000274B 29C0                <1> 	sub	eax, eax ; 0
  3089 0000274D F9                  <1> 	stc
  3090 0000274E EBE9                <1> 	jmp	short dpd_3	
  3091                              <1> 
  3092                              <1> duplicate_page_table:
  3093                              <1> 	; 31/12/2021
  3094                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3095                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3096                              <1> 	; 21/09/2015
  3097                              <1> 	; 20/07/2015
  3098                              <1> 	; 05/05/2015
  3099                              <1> 	; 28/04/2015
  3100                              <1> 	; 27/04/2015
  3101                              <1> 	; 18/04/2015
  3102                              <1> 	; 18/10/2014
  3103                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3104                              <1> 	;
  3105                              <1> 	; INPUT -> 
  3106                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3107                              <1> 	;       20/02/2017		 
  3108                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3109                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3110                              <1> 	; OUTPUT ->
  3111                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3112                              <1> 	;	      (with 'read only' attribute of page table entries)
  3113                              <1> 	;	20/02/2017
  3114                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3115                              <1> 	;	
  3116                              <1> 	;	CF = 1 -> error 
  3117                              <1> 	;
  3118                              <1> 	; Modified Registers -> EBP (except EAX)
  3119                              <1> 	;
  3120 00002750 E8ABFDFFFF          <1> 	call	allocate_page
  3121 00002755 725B                <1> 	jc	short dpt_err
  3122                              <1> 	;
  3123 00002757 50                  <1> 	push	eax ; *
  3124 00002758 56                  <1> 	push	esi
  3125 00002759 57                  <1> 	push	edi
  3126 0000275A 52                  <1> 	push	edx
  3127 0000275B 51                  <1> 	push	ecx
  3128                              <1> 	;
  3129 0000275C 89DE                <1> 	mov	esi, ebx
  3130 0000275E 89C7                <1> 	mov	edi, eax
  3131 00002760 89C2                <1> 	mov	edx, eax
  3132 00002762 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3133                              <1> dpt_0:
  3134 00002768 AD                  <1> 	lodsd
  3135 00002769 21C0                <1> 	and	eax, eax
  3136 0000276B 7435                <1> 	jz	short dpt_3
  3137 0000276D A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3138                              <1> 	; 24/12/2021
  3139 0000276F 7503                <1> 	jnz	short dpt_1
  3140                              <1> 	;jz	short dpt_p_err
  3141                              <1> 	; 31/12/2021
  3142 00002771 F9                  <1> 	stc
  3143 00002772 EB39                <1> 	jmp	short dpt_p_err
  3144                              <1> 
  3145                              <1> ; 24/12/2021
  3146                              <1> ; ('reload_page' procedure call is disabled)
  3147                              <1> ;
  3148                              <1> ;	; 20/07/2015
  3149                              <1> ;	; ebp = virtual (linear) address of the memory page
  3150                              <1> ;	call	reload_page ; 28/04/2015
  3151                              <1> ;	jc	short dpt_p_err
  3152                              <1> dpt_1:
  3153                              <1> 	; 21/09/2015
  3154 00002774 89C1                <1> 	mov	ecx, eax
  3155 00002776 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3156 0000277A F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3157 0000277D 751A                <1> 	jnz	short dpt_2
  3158                              <1> 	; Read only (parent) page
  3159                              <1> 	; 	- there is a third process which uses this page -
  3160                              <1> 	; Allocate a new page for the child process
  3161 0000277F E87CFDFFFF          <1> 	call	allocate_page
  3162 00002784 7227                <1> 	jc	short dpt_p_err
  3163 00002786 57                  <1> 	push	edi
  3164 00002787 56                  <1> 	push	esi
  3165 00002788 89CE                <1> 	mov	esi, ecx
  3166 0000278A 89C7                <1> 	mov	edi, eax
  3167 0000278C B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3168 00002791 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3169 00002793 5E                  <1> 	pop	esi
  3170 00002794 5F                  <1> 	pop	edi
  3171                              <1> 	;
  3172                              <1> 
  3173                              <1> ; 24/12/2021
  3174                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3175                              <1> ; 
  3176                              <1> ;	push	ebx
  3177                              <1> ;	push	eax
  3178                              <1> ;	; 20/07/2015
  3179                              <1> ;	mov	ebx, ebp
  3180                              <1> ;	; ebx = virtual (linear) address of the memory page
  3181                              <1> ;	call	add_to_swap_queue
  3182                              <1> ;	pop	eax
  3183                              <1> ;	pop	ebx
  3184                              <1> 
  3185                              <1> 	; 21/09/2015
  3186 00002795 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3187                              <1> 		; user + writable + present page
  3188 00002797 EB09                <1> 	jmp	short dpt_3
  3189                              <1> dpt_2:
  3190                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3191 00002799 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3192                              <1> 		    ; (read only page!)
  3193 0000279B 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3194 0000279E 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3195                              <1> dpt_3:
  3196 000027A2 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3197                              <1> 	;
  3198 000027A3 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3199                              <1> 	;
  3200 000027A9 39D7                <1> 	cmp	edi, edx
  3201 000027AB 72BB                <1> 	jb	short dpt_0
  3202                              <1> dpt_p_err:
  3203 000027AD 59                  <1> 	pop	ecx
  3204 000027AE 5A                  <1> 	pop	edx
  3205 000027AF 5F                  <1> 	pop	edi
  3206 000027B0 5E                  <1> 	pop	esi
  3207 000027B1 58                  <1> 	pop	eax ; *
  3208                              <1> dpt_err:
  3209 000027B2 C3                  <1> 	retn
  3210                              <1> 
  3211                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3212                              <1> 	; 31/12/2021
  3213                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3214                              <1> 	; 21/09/2015
  3215                              <1> 	; 19/09/2015
  3216                              <1> 	; 17/09/2015
  3217                              <1> 	; 28/08/2015
  3218                              <1> 	; 20/07/2015
  3219                              <1> 	; 28/06/2015
  3220                              <1> 	; 03/05/2015
  3221                              <1> 	; 30/04/2015
  3222                              <1> 	; 18/04/2015
  3223                              <1> 	; 12/04/2015
  3224                              <1> 	; 30/10/2014
  3225                              <1> 	; 11/09/2014
  3226                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3227                              <1> 	;
  3228                              <1> 	; Note: This is not an interrupt/exception handler.
  3229                              <1> 	;	This is a 'page fault remedy' subroutine 
  3230                              <1> 	;	which will be called by standard/uniform
  3231                              <1> 	;	exception handler.
  3232                              <1> 	;
  3233                              <1> 	; INPUT -> 
  3234                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3235                              <1> 	;
  3236                              <1> 	;	cr2 = the virtual (linear) address 
  3237                              <1> 	;	      which has caused to page fault (19/09/2015)
  3238                              <1> 	;
  3239                              <1> 	; OUTPUT ->
  3240                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3241                              <1> 	;	EAX = 0 -> no error
  3242                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3243                              <1> 	;
  3244                              <1> 	; Modified Registers -> none (except EAX)
  3245                              <1> 	;	
  3246                              <1>         ;
  3247                              <1>         ; ERROR CODE:
  3248                              <1> 	;	 31  .....	4   3	2   1	0
  3249                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3250                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3251                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3252                              <1> 	;
  3253                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3254                              <1>     	;		a page-protection violation. When not set,
  3255                              <1> 	;		it was caused by a non-present page.
  3256                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3257                              <1> 	;		a page write. When not set, it was caused
  3258                              <1> 	;		by a page read.
  3259                              <1> 	; U : USER    -	When set, the page fault was caused 
  3260                              <1> 	;		while CPL = 3. 
  3261                              <1> 	;		This does not necessarily mean that
  3262                              <1> 	;		the page fault was a privilege violation.
  3263                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3264                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3265                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3266                              <1> 	;     FETCH	an instruction fetch
  3267                              <1> 	;
  3268                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3269                              <1> 	;  31               22                  12 11                    0
  3270                              <1> 	; +-------------------+-------------------+-----------------------+
  3271                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3272                              <1>        	; +-------------------+-------------------+-----------------------+
  3273                              <1> 	;
  3274                              <1> 
  3275                              <1> 	;; CR3 REGISTER (Control Register 3)
  3276                              <1> 	;  31                                   12             5 4 3 2   0
  3277                              <1> 	; +---------------------------------------+-------------+---+-----+
  3278                              <1>       	; |                                       |  		|P|P|     |
  3279                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3280                              <1>       	; |                                       | 		|D|T|     |
  3281                              <1>    	; +---------------------------------------+-------------+---+-----+
  3282                              <1> 	;
  3283                              <1> 	;	PWT    - WRITE THROUGH
  3284                              <1> 	;	PCD    - CACHE DISABLE		
  3285                              <1> 	;
  3286                              <1> 	;
  3287                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3288                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3289                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3290                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3291                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3292                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3293                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3294                              <1> 	;
  3295                              <1>         ;       P      - PRESENT
  3296                              <1>         ;       R/W    - READ/WRITE
  3297                              <1>         ;       U/S    - USER/SUPERVISOR
  3298                              <1> 	;	PWT    - WRITE THROUGH
  3299                              <1> 	;	PCD    - CACHE DISABLE	
  3300                              <1> 	;	A      - ACCESSED	
  3301                              <1>         ;       D      - DIRTY (IGNORED)
  3302                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3303                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3304                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3305                              <1> 	;
  3306                              <1> 	;
  3307                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3308                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3309                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3310                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3311                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3312                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3313                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3314                              <1> 	;
  3315                              <1>         ;       P      - PRESENT
  3316                              <1>         ;       R/W    - READ/WRITE
  3317                              <1>         ;       U/S    - USER/SUPERVISOR
  3318                              <1> 	;	PWT    - WRITE THROUGH
  3319                              <1> 	;	PCD    - CACHE DISABLE	
  3320                              <1> 	;	A      - ACCESSED	
  3321                              <1>         ;       D      - DIRTY
  3322                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3323                              <1> 	;	G      - GLOBAL	 
  3324                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3325                              <1> 	;
  3326                              <1> 	;
  3327                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3328                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3329                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3330                              <1>       	; |                                       |     | | | | | | |U|R| |
  3331                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3332                              <1>       	; |                                       |     | | | | | | |S|W| |
  3333                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3334                              <1> 	;
  3335                              <1>         ;       P      - PRESENT
  3336                              <1>         ;       R/W    - READ/WRITE
  3337                              <1>         ;       U/S    - USER/SUPERVISOR
  3338                              <1>         ;       D      - DIRTY
  3339                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3340                              <1> 	;
  3341                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3342                              <1> 	;
  3343                              <1> 	;
  3344                              <1> 	;; Invalid Page Table Entry
  3345                              <1> 	; 31                                                           1 0
  3346                              <1>       	; +-------------------------------------------------------------+-+
  3347                              <1>       	; |                                                             | |
  3348                              <1>       	; |                          AVAILABLE                          |0|
  3349                              <1>       	; |                                                             | |
  3350                              <1>       	; +-------------------------------------------------------------+-+
  3351                              <1> 	;
  3352                              <1> 
  3353 000027B3 53                  <1> 	push	ebx
  3354 000027B4 52                  <1> 	push	edx
  3355 000027B5 51                  <1> 	push	ecx
  3356                              <1> 	;
  3357                              <1> 	; 21/09/2015 (debugging)
  3358 000027B6 FF05[73660000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3359 000027BC FF05[FC620000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3360                              <1> 	; 28/06/2015
  3361                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3362 000027C2 8A15[F4620000]      <1> 	mov	dl, [error_code]
  3363                              <1> 	;
  3364 000027C8 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3365                              <1> 			; sign
  3366 000027CB 7425                <1> 	jz	short pfh_alloc_np
  3367                              <1> 	; 
  3368                              <1> 	; If it is not a 'write on read only page' type page fault
  3369                              <1> 	; major page fault error with minor reason must be returned without 
  3370                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3371                              <1> 	; after return here!
  3372                              <1> 	; Page fault will be remedied, by copying page contents
  3373                              <1> 	; to newly allocated page with write permission;
  3374                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3375                              <1> 	; used for working with minimum possible memory usage. 
  3376                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3377                              <1> 	; process with 'read only' flag. If the child process attempts to
  3378                              <1> 	; write on these read only pages, page fault will be directed here
  3379                              <1> 	; for allocating a new page with same data/content. 
  3380                              <1> 	;
  3381                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3382                              <1> 	; will not force to separate CODE and DATA space 
  3383                              <1> 	; in a process/program... 
  3384                              <1> 	; CODE segment/section may contain DATA!
  3385                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3386                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3387                              <1> 	;	
  3388 000027CD F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3389                              <1> 			; sign
  3390 000027D0 7418                <1>         jz      pfh_p_err
  3391                              <1> 	; 31/08/2015
  3392 000027D2 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3393                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3394 000027D5 7413                <1>         jz	short pfh_pv_err
  3395                              <1> 	;
  3396                              <1> 	; make a new page and copy the parent's page content
  3397                              <1> 	; as the child's new page content
  3398                              <1> 	;
  3399 000027D7 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3400                              <1> 			 ; which has caused to page fault
  3401 000027DA E87C000000          <1> 	call 	copy_page
  3402 000027DF 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3403                              <1> 	;
  3404 000027E1 EB72                <1>         jmp     pfh_cpp_ok
  3405                              <1> 
  3406                              <1> 	; 31/12/2021 (short jump)
  3407                              <1> pfh_im_err:
  3408 000027E3 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3409                              <1> 			; Major (Primary) Error: Page Fault
  3410                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3411 000027E8 EB6D                <1> 	jmp	short pfh_err_retn
  3412                              <1> 
  3413                              <1> 	; 31/12/2021
  3414                              <1> pfh_p_err: ; 09/03/2015
  3415                              <1> pfh_pv_err:
  3416                              <1> 	; Page fault was caused by a protection-violation
  3417 000027EA B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3418                              <1> 			; Major (Primary) Error: Page Fault
  3419                              <1> 			; Minor (Secondary) Error: Protection violation !
  3420 000027EF F9                  <1> 	stc
  3421 000027F0 EB65                <1> 	jmp	short pfh_err_retn
  3422                              <1> 	
  3423                              <1> pfh_alloc_np:
  3424 000027F2 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3425 000027F7 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3426                              <1> pfh_chk_cpl:
  3427                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3428                              <1> 		; (Lower 12 bits are ZERO, because 
  3429                              <1> 		;	the address is on a page boundary)
  3430 000027F9 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3431 000027FC 7505                <1> 	jnz	short pfh_um
  3432                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3433 000027FE 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3434                              <1> 			 ; of the current/active page directory
  3435                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3436                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3437 00002801 EB06                <1> 	jmp	short pfh_get_pde
  3438                              <1> 	;
  3439                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3440 00002803 8B1D[63660000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3441                              <1> 			; Physical address of the USER's page directory
  3442                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3443                              <1> pfh_get_pde:
  3444 00002809 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3445 0000280C 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3446                              <1> 			 ; which has been caused to page fault
  3447                              <1> 			 ;
  3448 0000280F C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3449 00002812 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3450                              <1> 	;
  3451 00002815 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3452 00002817 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3453 00002819 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3454 0000281C 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3455                              <1> 			  	  ; set/validate page directory entry
  3456 0000281E 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3457 00002823 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3458 00002825 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3459 00002827 EB16                <1> 	jmp	short pfh_get_pte
  3460                              <1> pfh_set_pde:
  3461                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3462                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3463                              <1> 	;
  3464 00002829 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3465 0000282B 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3466 0000282D 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3467 0000282F 89C3                <1> 	mov	ebx, eax
  3468 00002831 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3469 00002836 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3470                              <1> pfh_spde_1:
  3471                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3472 00002838 89C1                <1> 	mov	ecx, eax
  3473 0000283A E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3474                              <1> pfh_get_pte:
  3475 0000283F 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3476                              <1> 			 ; which has been caused to page fault
  3477 00002842 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3478 00002844 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3479                              <1> 			 ; higher 20 bits of the page fault address 
  3480 00002847 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3481 0000284C C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3482 0000284F 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3483                              <1> ; 24/12/2021
  3484                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3485                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3486                              <1> ; 24/12/2021
  3487                              <1> ; ('swap_in' procedure call has been disabled)
  3488                              <1> ;
  3489                              <1> ;	and	eax, eax
  3490                              <1> ;	jz	short pfh_gpte_1
  3491                              <1> ;	; 20/07/2015
  3492                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3493                              <1> ;	push	ebp ; 20/07/2015
  3494                              <1> ;	mov	ebp, cr2
  3495                              <1> ;		; ECX = physical address of the page table entry
  3496                              <1> ;		; EBX = Memory page address (physical!)
  3497                              <1> ;		; EAX = Swap disk (offset) address
  3498                              <1> ;		; EBP = virtual address (page fault address)
  3499                              <1> ;	call	swap_in
  3500                              <1> ;	pop	ebp
  3501                              <1> ;	jc      short pfh_err_retn
  3502                              <1> ;	xchg	ecx, ebx
  3503                              <1> ;		; EBX = physical address of the page table entry
  3504                              <1> ;		; ECX = new page
  3505                              <1> pfh_gpte_1:
  3506 00002851 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3507 00002853 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3508                              <1> pfh_cpp_ok:
  3509                              <1> ; 24/12/2021
  3510                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3511                              <1> ;
  3512                              <1> ;	; 20/07/2015
  3513                              <1> ;	mov	ebx, cr2
  3514                              <1> ;	call 	add_to_swap_queue
  3515                              <1> 	;
  3516                              <1> 	; The new PTE (which contains the new page) will be added to 
  3517                              <1> 	; the swap queue, here. 
  3518                              <1> 	; (Later, if memory will become insufficient, 
  3519                              <1> 	; one page will be swapped out which is at the head of 
  3520                              <1> 	; the swap queue by using FIFO and access check methods.)
  3521                              <1> 	;
  3522 00002855 31C0                <1> 	xor	eax, eax  ; 0
  3523                              <1> 	;
  3524                              <1> pfh_err_retn:
  3525 00002857 59                  <1> 	pop	ecx
  3526 00002858 5A                  <1> 	pop	edx
  3527 00002859 5B                  <1> 	pop	ebx
  3528 0000285A C3                  <1> 	retn 
  3529                              <1> 	
  3530                              <1> copy_page:
  3531                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3532                              <1> 	; 16/04/2021
  3533                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3534                              <1> 	; 22/09/2015
  3535                              <1> 	; 21/09/2015
  3536                              <1> 	; 19/09/2015
  3537                              <1> 	; 07/09/2015
  3538                              <1> 	; 31/08/2015
  3539                              <1> 	; 20/07/2015
  3540                              <1> 	; 05/05/2015
  3541                              <1> 	; 03/05/2015
  3542                              <1> 	; 18/04/2015
  3543                              <1> 	; 12/04/2015
  3544                              <1> 	; 30/10/2014
  3545                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3546                              <1> 	;
  3547                              <1> 	; INPUT -> 
  3548                              <1> 	;	EBX = Virtual (linear) address of source page
  3549                              <1> 	;	     (Page fault address)
  3550                              <1> 	; OUTPUT ->
  3551                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3552                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3553                              <1> 	;	EAX = 0 (CF = 1) 
  3554                              <1> 	;		if there is not a free page to be allocated
  3555                              <1> 	;	(page content of the source page will be copied
  3556                              <1> 	;	onto the target/new page) 	
  3557                              <1> 	;
  3558                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3559                              <1> 	;
  3560                              <1> 
  3561                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3562                              <1> 	; INPUT: 
  3563                              <1> 	;	EBX = Virtual (linear) address of source page
  3564                              <1> 	;	     (Page fault address)
  3565                              <1> 	; OUTPUT:
  3566                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3567                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3568                              <1> 	;	EAX = 0 (CF = 1) 
  3569                              <1> 	;		if there is not a free page to be allocated
  3570                              <1> 	;	(page content of the source page will be copied
  3571                              <1> 	;	onto the target/new page) 	
  3572                              <1> 	;
  3573                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3574                              <1> 	
  3575 0000285B 56                  <1> 	push	esi ; *
  3576 0000285C 57                  <1> 	push	edi ; **
  3577                              <1> 	; 16/04/2021
  3578                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3579                              <1> 	;push	ebx ; ***
  3580                              <1> 	;push	ecx ; ****
  3581 0000285D 31F6                <1> 	xor 	esi, esi
  3582 0000285F C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3583 00002862 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3584 00002864 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3585 00002867 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3586 0000286A 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3587 0000286C 031D[63660000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3588 00002872 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3589 00002874 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3590 00002878 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3591 0000287A 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3592 00002880 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3593 00002884 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3594                              <1> 	; 07/09/2015
  3595 00002886 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3596                              <1> 				     ; read only page as a child process?)	
  3597 0000288B 7509                <1> 	jnz	short cpp_0 ; yes
  3598 0000288D 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3599 0000288F 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3600 00002894 EB32                <1> 	jmp	short cpp_1
  3601                              <1> cpp_0:
  3602 00002896 89FE                <1> 	mov	esi, edi
  3603 00002898 0335[67660000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3604 0000289E 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3605 000028A0 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3606 000028A4 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3607 000028A6 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3608 000028AC 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3609 000028B0 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3610 000028B2 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3611                              <1> 	; 21/09/2015
  3612 000028B4 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3613 000028B6 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3614                              <1> 	;
  3615 000028BA F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3616 000028BD 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3617                              <1> 	;
  3618 000028BF 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3619 000028C4 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3620 000028C6 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3621                              <1> 			    ; Convert child's page to writable page
  3622                              <1> cpp_1:
  3623 000028C8 E833FCFFFF          <1> 	call	allocate_page
  3624 000028CD 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3625 000028CF 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3626 000028D1 7405                <1> 	jz	short cpp_2
  3627                              <1> 		; Convert read only page to writable page 
  3628                              <1> 		;(for the parent of the current process)
  3629                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3630                              <1> 	; 22/09/2015
  3631 000028D3 890E                <1> 	mov	[esi], ecx
  3632 000028D5 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3633                              <1> 				 ; 1+2+4 = 7
  3634                              <1> cpp_2:
  3635 000028D8 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3636                              <1> 	; 07/09/2015
  3637 000028DA 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3638 000028DC B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3639 000028E1 F3A5                <1> 	rep	movsd ; 31/08/2015
  3640                              <1> cpp_3:		
  3641 000028E3 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3642 000028E5 8903                <1> 	mov	[ebx], eax ; Update PTE
  3643 000028E7 28C0                <1> 	sub	al, al ; clear attributes
  3644                              <1> cpp_4:
  3645                              <1> 	; 16/04/2021
  3646                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3647                              <1> 	;pop	ecx ; ****
  3648                              <1> 	;pop	ebx ; ***
  3649 000028E9 5F                  <1> 	pop	edi ; **
  3650 000028EA 5E                  <1> 	pop	esi ; *
  3651 000028EB C3                  <1> 	retn
  3652                              <1> 
  3653                              <1> ;; 28/04/2015
  3654                              <1> ;; 24/10/2014
  3655                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3656                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3657                              <1> ;;
  3658                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3659                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3660                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3661                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3662                              <1> ;;
  3663                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3664                              <1> ;;
  3665                              <1> ;; Method:
  3666                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3667                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3668                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3669                              <1> ;;	When a new page is being allocated, swap queue is updated
  3670                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3671                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3672                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3673                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3674                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3675                              <1> ;;	offset value becomes it's previous offset value - 4.
  3676                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3677                              <1> ;;	the queue/list is not shifted.
  3678                              <1> ;;	After the queue/list shift, newly allocated page is added
  3679                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3680                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3681                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3682                              <1> ;;	
  3683                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3684                              <1> ;;	the first non-accessed, writable page in the list, 
  3685                              <1> ;;	from the head to the tail. The list is shifted to left 
  3686                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3687                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3688                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3689                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3690                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3691                              <1> ;;	procedure will be failed)...
  3692                              <1> ;;
  3693                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3694                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3695                              <1> ;;	(PTE) will be added to the tail of the queue after
  3696                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3697                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3698                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3699                              <1> ;;
  3700                              <1> ;;
  3701                              <1> ;;	
  3702                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3703                              <1> ;;
  3704                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3705                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3706                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3707                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3708                              <1> ;;
  3709                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3710                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3711                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3712                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3713                              <1> ;; 		 (entire swap space must be accessed by using
  3714                              <1> ;;		 31 bit offset address) 
  3715                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3716                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3717                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3718                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3719                              <1> ;;
  3720                              <1> ;; 					
  3721                              <1> ;; Method:
  3722                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3723                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3724                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3725                              <1> ;;	Swapping out is performed by using swap page queue.
  3726                              <1> ;;
  3727                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3728                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3729                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3730                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3731                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3732                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3733                              <1> ;;	calculated by adding offset value to the swap partition's 
  3734                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3735                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3736                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3737                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3738                              <1> ;;	is in a partitioned virtual hard disk.) 
  3739                              <1> ;;
  3740                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3741                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3742                              <1> ;;
  3743                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3744                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3745                              <1> ;;
  3746                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3747                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3748                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3749                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3750                              <1> ;;	it means relevant (respective) block is in use, and, 
  3751                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3752                              <1> ;;      swap disk/file block is free.
  3753                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3754                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3755                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3756                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3757                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3758                              <1> ;;	------------------------------------------------------------
  3759                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3760                              <1> ;;	------------------------------------------------------------
  3761                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3762                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3763                              <1> ;;
  3764                              <1> ;;	..............................................................
  3765                              <1> ;;
  3766                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3767                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3768                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3769                              <1> ;;	position with value of 1 on the table is converted to swap
  3770                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3771                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3772                              <1> ;;	number of physical swap disk or virtual swap disk)
  3773                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3774                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3775                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3776                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3777                              <1> ;;	If disk write procedure returns with error or free count of 
  3778                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3779                              <1> ;;	'insufficient memory error' (cf=1). 
  3780                              <1> ;;
  3781                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3782                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3783                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3784                              <1> ;;	free blocks after a disk write error. It will return to 
  3785                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3786                              <1> ;;
  3787                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3788                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3789                              <1> ;;	address (cf=0). 
  3790                              <1> ;;
  3791                              <1> ;;	..............................................................
  3792                              <1> ;;
  3793                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3794                              <1> ;;	file sectors at specified memory page. Then page allocation
  3795                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3796                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3797                              <1> ;;	to do, except to terminate the process which is the owner of
  3798                              <1> ;;	the swapped page.
  3799                              <1> ;;
  3800                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3801                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3802                              <1> ;;	updates [swpd_first] pointer if it is required.
  3803                              <1> ;;
  3804                              <1> ;;	..............................................................	 
  3805                              <1> ;;
  3806                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3807                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3808                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3809                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3810                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3811                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3812                              <1> ;;
  3813                              <1> 
  3814                              <1> ; 24/12/2021
  3815                              <1> ; ('swap_in' procedure call is disabled)
  3816                              <1> 
  3817                              <1> ;swap_in:
  3818                              <1> 	; 31/08/2015
  3819                              <1> 	; 20/07/2015
  3820                              <1> 	; 28/04/2015
  3821                              <1> 	; 18/04/2015
  3822                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3823                              <1> 	;
  3824                              <1> 	; INPUT -> 
  3825                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3826                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3827                              <1> 	;	EAX = Offset Address for the swapped page on the
  3828                              <1> 	;	      swap disk or in the swap file.
  3829                              <1> 	;
  3830                              <1> 	; OUTPUT ->
  3831                              <1> 	;	EAX = 0 if loading at memory has been successful
  3832                              <1> 	;
  3833                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3834                              <1> 	;		  or sector not present or drive not ready
  3835                              <1> 	;	     EAX = Error code
  3836                              <1> 	;	     [u.error] = EAX 
  3837                              <1> 	;		       = The last error code for the process
  3838                              <1> 	;		         (will be reset after returning to user)	  
  3839                              <1> 	;
  3840                              <1> 	; Modified Registers -> EAX
  3841                              <1> 	;
  3842                              <1> 
  3843                              <1> ;       cmp     dword [swp_drv], 0
  3844                              <1> ;	jna	short swpin_dnp_err
  3845                              <1> ;
  3846                              <1> ;	cmp	eax, [swpd_size]
  3847                              <1> ;	jnb	short swpin_snp_err
  3848                              <1> ;
  3849                              <1> ;	push	esi
  3850                              <1> ;	push	ebx
  3851                              <1> ;	push	ecx
  3852                              <1> ;	mov	esi, [swp_drv]	
  3853                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3854                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3855                              <1> ;		; size different than 512 bytes, logical disk sector
  3856                              <1> ;		; size is 512 bytes and disk reading procedure
  3857                              <1> ;		; will be performed for reading 4096 bytes
  3858                              <1> ;		; (2*2048, 8*512). 
  3859                              <1> ;	; ESI = Logical disk description table address
  3860                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3861                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3862                              <1> ;	; ECX = Sector count ; 8 sectors
  3863                              <1> ;	push	eax
  3864                              <1> ;	call	logical_disk_read
  3865                              <1> ;	pop	eax
  3866                              <1> ;	jnc	short swpin_read_ok
  3867                              <1> ;	;
  3868                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3869                              <1> ;	mov	[u.error], eax
  3870                              <1> ;	jmp	short swpin_retn
  3871                              <1> ;	;
  3872                              <1> ;swpin_read_ok:
  3873                              <1> ;	; EAX = Offset address (logical sector number)
  3874                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3875                              <1> ;	;
  3876                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3877                              <1> ;	; 20/07/2015
  3878                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3879                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3880                              <1> ;	mov	bl, [u.uno] ; current process number
  3881                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3882                              <1> ;	call	swap_queue_shift
  3883                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3884                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3885                              <1> ;	; zf = 1
  3886                              <1> ;swpin_retn:
  3887                              <1> ;	pop	ecx
  3888                              <1> ;	pop	ebx
  3889                              <1> ;	pop	esi
  3890                              <1> ;	retn
  3891                              <1> ;
  3892                              <1> ;swpin_dnp_err:
  3893                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3894                              <1> ;swpin_err_retn:
  3895                              <1> ;	mov	[u.error], eax
  3896                              <1> ;	stc
  3897                              <1> ;	retn
  3898                              <1> ;
  3899                              <1> ;swpin_snp_err:
  3900                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3901                              <1> ;	jmp	short swpin_err_retn
  3902                              <1> 
  3903                              <1> ; 24/12/2021
  3904                              <1> ; ('swap_out' procedure call is disabled)
  3905                              <1> 
  3906                              <1> ;swap_out:
  3907                              <1> 	; 10/06/2016
  3908                              <1> 	; 07/06/2016
  3909                              <1>         ; 23/05/2016
  3910                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3911                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3912                              <1> 	;
  3913                              <1> 	; INPUT -> 
  3914                              <1> 	;	none
  3915                              <1> 	;
  3916                              <1> 	; OUTPUT ->
  3917                              <1> 	;	EAX = Physical page address (which is swapped out
  3918                              <1> 	;	      for allocating a new page)
  3919                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3920                              <1> 	;		  or sector not present or drive not ready
  3921                              <1> 	;	     EAX = Error code
  3922                              <1> 	;	     [u.error] = EAX 
  3923                              <1> 	;		       = The last error code for the process
  3924                              <1> 	;		         (will be reset after returning to user)	  
  3925                              <1> 	;
  3926                              <1> 	; Modified Registers -> none (except EAX)
  3927                              <1> 	;
  3928                              <1> 
  3929                              <1> ;	cmp 	word [swpq_count], 1
  3930                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3931                              <1> ;
  3932                              <1> ;       ;cmp    dword [swp_drv], 1
  3933                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3934                              <1> ;
  3935                              <1> ;       cmp     dword [swpd_free], 1
  3936                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3937                              <1> ;
  3938                              <1> ;	push	ebx ; *
  3939                              <1> ;swpout_1:
  3940                              <1> ;	; 10/06/2016
  3941                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3942                              <1> ;	call	swap_queue_shift
  3943                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3944                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3945                              <1> ;				       ; pointer in the swap queue
  3946                              <1> ;	; EAX = PTE value of the page
  3947                              <1> ;	; EBX = PTE address of the page
  3948                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3949                              <1> ;	;
  3950                              <1> ;	; 07/06/2016
  3951                              <1> ;	; 19/05/2016
  3952                              <1> ;	; check this page is in timer events or not
  3953                              <1> ;	
  3954                              <1> ;swpout_timer_page_0:
  3955                              <1> ;	push	edx ; **
  3956                              <1> ;
  3957                              <1> ;	; 07/06/2016
  3958                              <1> ;	cmp	byte [timer_events], 0 
  3959                              <1> ;	jna	short swpout_2
  3960                              <1> ;	;
  3961                              <1> ;	mov	dl, [timer_events]
  3962                              <1> ;
  3963                              <1> ;	push	ecx ; ***
  3964                              <1> ;	push	ebx ; ****
  3965                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3966                              <1> ;			       ; structures 
  3967                              <1> ;swpout_timer_page_1:
  3968                              <1> ;	mov	cl, [ebx]
  3969                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3970                              <1> ;	jz	short swpout_timer_page_3
  3971                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3972                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3973                              <1> ;				; of the response byte address, to
  3974                              <1> ;				; get beginning of the page address)
  3975                              <1> ;	cmp	eax, ecx
  3976                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3977                              <1> ;	
  3978                              <1> ;	; !same page!
  3979                              <1> ;	;
  3980                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3981                              <1> ;	; This page will be used by the kernel to put timer event
  3982                              <1> ;	; response (signal return) byte at the requested address;
  3983                              <1> ;	; in order to prevent a possible wrong write (while
  3984                              <1> ;	; this page is swapped out) on physical memory,
  3985                              <1> ;	; we must protect this page against to be swapped out!
  3986                              <1> ;	;
  3987                              <1> ;	pop	ebx ; ****
  3988                              <1> ;	pop	ecx ; ***
  3989                              <1> ;	pop	edx ; **
  3990                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3991                              <1> ; 
  3992                              <1> ;swpout_timer_page_2:
  3993                              <1> ;	; 07/06/2016
  3994                              <1> ;	dec	dl
  3995                              <1> ;	jz	short swpout_timer_page_4
  3996                              <1> ;swpout_timer_page_3:
  3997                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3998                              <1> ;	;jnb	short swpout_timer_page_4
  3999                              <1> ;	add	ebx, 16
  4000                              <1> ;	jmp	short swpout_timer_page_1	
  4001                              <1> ;
  4002                              <1> ;swpout_timer_page_4:
  4003                              <1> ;	pop	ebx ; ****
  4004                              <1> ;	pop	ecx ; ***
  4005                              <1> ;swpout_2:
  4006                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4007                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4008                              <1> ;	;
  4009                              <1> ;	call	link_swap_block
  4010                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4011                              <1> ;				       ; because [swpd_free] value
  4012                              <1> ;				       ; was checked at the beginging. 	
  4013                              <1> ;	pop	edx ; **
  4014                              <1> ;	pop	ebx ; *
  4015                              <1> ;	jmp	short swpout_nfspc_err 
  4016                              <1> ;swpout_3:
  4017                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4018                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4019                              <1> ;	;	
  4020                              <1> ;	push	esi ; **
  4021                              <1> ;	push	ecx ; ***
  4022                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4023                              <1> ;	mov	esi, [swp_drv]	
  4024                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4025                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4026                              <1> ;		; size different than 512 bytes, logical disk sector
  4027                              <1> ;		; size is 512 bytes and disk writing procedure
  4028                              <1> ;		; will be performed for writing 4096 bytes
  4029                              <1> ;		; (2*2048, 8*512). 
  4030                              <1> ;	; ESI = Logical disk description table address
  4031                              <1> ;	; EBX = Buffer (Page) address
  4032                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4033                              <1> ;	; ECX = Sector count ; 8 sectors
  4034                              <1> ;	; edx = PTE address
  4035                              <1> ;	call	logical_disk_write
  4036                              <1> ;	; edx = PTE address
  4037                              <1> ;	pop	ecx ; sector address	
  4038                              <1> ;	jnc	short swpout_write_ok
  4039                              <1> ;	;
  4040                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4041                              <1> ;swpout_dw_err:
  4042                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4043                              <1> ;	mov	[u.error], eax
  4044                              <1> ;	jmp	short swpout_retn
  4045                              <1> ;	;
  4046                              <1> ;swpout_write_ok:
  4047                              <1> ;	; EBX = Buffer (page) address
  4048                              <1> ;	; EDX = Page Table Entry address
  4049                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4050                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4051                              <1> ;	mov 	[edx], ecx 
  4052                              <1> ;		; bit 0 = 0 (swapped page)
  4053                              <1> ;	mov	eax, ebx
  4054                              <1> ;swpout_retn:
  4055                              <1> ;	pop	ecx ; ***
  4056                              <1> ;	pop	esi ; **
  4057                              <1> ;	pop	ebx ; *
  4058                              <1> ;	retn
  4059                              <1> ;
  4060                              <1> ;;swpout_dnp_err:
  4061                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4062                              <1> ;;	jmp	short swpout_err_retn
  4063                              <1> ;swpout_nfspc_err:
  4064                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4065                              <1> ;swpout_err_retn:
  4066                              <1> ;	mov	[u.error], eax
  4067                              <1> ;	;stc
  4068                              <1> ;	retn
  4069                              <1> ;swpout_npts_err:
  4070                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4071                              <1> ;	pop	ebx
  4072                              <1> ;	jmp	short swpout_err_retn
  4073                              <1> ;swpout_im_err:
  4074                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4075                              <1> ;	jmp	short swpout_err_retn
  4076                              <1> 
  4077                              <1> ; 24/12/2021
  4078                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4079                              <1> 
  4080                              <1> ;swap_queue_shift:
  4081                              <1> 	; 26/03/2017
  4082                              <1> 	; 10/06/2016
  4083                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4084                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4085                              <1> 	;
  4086                              <1> 	; INPUT ->
  4087                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4088                              <1> 	;	      and process number combination (bit 0 to 11)
  4089                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4090                              <1> 	;	
  4091                              <1> 	; OUTPUT ->
  4092                              <1> 	;	If EBX input > 0 
  4093                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4094                              <1> 	; 	   from the tail to the head, up to entry offset
  4095                              <1> 	; 	   which points to EBX input value or nothing
  4096                              <1> 	;	   to do if EBX value is not found on the queue.
  4097                              <1> 	;	   (The entry -with EBX value- will be removed
  4098                              <1> 	;	   from the queue if it is found.)
  4099                              <1> 	;
  4100                              <1> 	;	   EAX = 0		
  4101                              <1> 	;
  4102                              <1> 	;	If EBX input = 0
  4103                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4104                              <1> 	; 	   from the tail to the head, if the PTE address
  4105                              <1> 	;	   which is pointed in head of the queue is marked
  4106                              <1> 	;	   as "accessed" or it is marked as "non present".
  4107                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4108                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4109                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4110                              <1> 	;	   -without dropping pointer of the PTE from 
  4111                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4112                              <1> 	;	   Pointer in the head will be moved into the tail,
  4113                              <1> 	;	   other PTEs will be shifted on head direction.)
  4114                              <1> 	;
  4115                              <1> 	;	   Swap queue will be shifted up to the first
  4116                              <1> 	;	   'present' or 'non accessed' page will be found
  4117                              <1> 	;	   (as pointed) on the queue head (then it will be
  4118                              <1>         ;          removed/dropped from the queue).
  4119                              <1> 	;
  4120                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4121                              <1> 	;		 (it's pointer -virtual address-) dropped
  4122                              <1> 	;		 (removed) from swap queue.
  4123                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4124                              <1> 	;	         which is (it's pointer -virtual address-)
  4125                              <1> 	;		 dropped (removed) from swap queue.
  4126                              <1> 	;
  4127                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4128                              <1> 	;
  4129                              <1> 	; Modified Registers -> EAX, EBX
  4130                              <1> 	;
  4131                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4132                              <1> ;	and	ax, ax
  4133                              <1> ;	jz	short swpqs_retn
  4134                              <1> ;	push	edi
  4135                              <1> ;	push	esi
  4136                              <1> ;	push	ecx
  4137                              <1> ;	mov	esi, swap_queue
  4138                              <1> ;	mov	ecx, eax
  4139                              <1> ;	or	ebx, ebx
  4140                              <1> ;	jz	short swpqs_7
  4141                              <1> ;swpqs_1:
  4142                              <1> ;	lodsd
  4143                              <1> ;	cmp	eax, ebx
  4144                              <1> ;	je	short swpqs_2
  4145                              <1> ;	loop	swpqs_1
  4146                              <1> ;	; 10/06/2016
  4147                              <1> ;	sub	eax, eax 
  4148                              <1> ;	jmp	short swpqs_6
  4149                              <1> ;swpqs_2:
  4150                              <1> ;	mov	edi, esi
  4151                              <1> ;	sub 	edi, 4
  4152                              <1> ;swpqs_3:
  4153                              <1> ;	dec	word [swpq_count]
  4154                              <1> ;	jz	short swpqs_5
  4155                              <1> ;swpqs_4:
  4156                              <1> ;	dec 	ecx
  4157                              <1> ;	rep	movsd	; shift up (to the head)
  4158                              <1> ;swpqs_5:
  4159                              <1> ;	xor	eax, eax
  4160                              <1> ;	mov	[edi], eax
  4161                              <1> ;swpqs_6:
  4162                              <1> ;	pop	ecx
  4163                              <1> ;	pop	esi
  4164                              <1> ;	pop	edi
  4165                              <1> ;swpqs_retn:
  4166                              <1> ;	retn		
  4167                              <1> ;swpqs_7:
  4168                              <1> ;	mov	edi, esi ; head
  4169                              <1> ;	lodsd
  4170                              <1> ;	; 20/07/2015
  4171                              <1> ;	mov	ebx, eax
  4172                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4173                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4174                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4175                              <1> ;		      ; ax = process number (1 to 4095)
  4176                              <1> ;	cmp	al, [u.uno]
  4177                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4178                              <1> ;	jne	short swpqs_8
  4179                              <1> ;	mov	eax, [u.pgdir]
  4180                              <1> ;	jmp	short swpqs_9
  4181                              <1> ;swpqs_8:
  4182                              <1> ;	; 09/06/2016
  4183                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4184                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4185                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4186                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4187                              <1> ;
  4188                              <1> ;	;shl	ax, 2
  4189                              <1> ;	shl	al, 2
  4190                              <1> ;	mov 	eax, [eax+p.upage-4]
  4191                              <1> ;	or	eax, eax
  4192                              <1> ;	jz	short swpqs_3 ; invalid upage
  4193                              <1> ;	add	eax, u.pgdir - user
  4194                              <1> ;			 ; u.pgdir value for the process
  4195                              <1> ;			 ; is in [eax]
  4196                              <1> ;	mov	eax, [eax]
  4197                              <1> ;	and	eax, eax
  4198                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4199                              <1> ;swpqs_9:
  4200                              <1> ;	push	edx
  4201                              <1> ;	; eax = page directory
  4202                              <1> ;	; ebx = virtual address
  4203                              <1> ;	call	get_pte
  4204                              <1> ;	mov	ebx, edx	; PTE address
  4205                              <1> ;	pop	edx
  4206                              <1> ;	; 10/06/2016
  4207                              <1> ;	jc	short swpqs_13 ; empty PDE
  4208                              <1> ;	; EAX = PTE value
  4209                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4210                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4211                              <1> ;			        ; from the queue (head)
  4212                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4213                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4214                              <1> ;			        ; from the queue (head) 	
  4215                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4216                              <1> ;	;jnz	short swpqs_11  ; present
  4217                              <1> ;			        ; accessed page
  4218                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4219                              <1> ;	jc	short swpqs_11  ; accessed page
  4220                              <1> ;
  4221                              <1> ;	dec	ecx
  4222                              <1> ;	mov	[swpq_count], cx
  4223                              <1> ;       jz      short swpqs_10
  4224                              <1> ;		; esi = head + 4
  4225                              <1> ;		; edi = head
  4226                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4227                              <1> ;swpqs_10:
  4228                              <1> ;	mov	[edi], ecx ; 0
  4229                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4230                              <1> ;
  4231                              <1> ;swpqs_11:
  4232                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4233                              <1> ;	; Rotation (head -> tail)
  4234                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4235                              <1> ;	jz	short swpqs_10
  4236                              <1> ;		; esi = head + 4
  4237                              <1> ;		; edi = head
  4238                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4239                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4240                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4241                              <1> ;
  4242                              <1> ;	mov	cx, [swpq_count]
  4243                              <1> ;
  4244                              <1> ;swpqs_12:
  4245                              <1> ;	mov	esi, swap_queue ; head
  4246                              <1> ;       jmp     swpqs_7
  4247                              <1> ;
  4248                              <1> ;swpqs_13:
  4249                              <1> ;	dec	ecx
  4250                              <1> ;	mov	[swpq_count], cx
  4251                              <1> ;       jz      swpqs_5
  4252                              <1> ;	jmp	short swpqs_12
  4253                              <1> 
  4254                              <1> ; 24/12/2021
  4255                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4256                              <1> 
  4257                              <1> ;add_to_swap_queue:
  4258                              <1> 	; 20/02/2017
  4259                              <1> 	; 20/07/2015
  4260                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4261                              <1> 	;
  4262                              <1> 	; Adds new page to swap queue
  4263                              <1> 	; (page directories and page tables must not be added
  4264                              <1> 	; to swap queue)	
  4265                              <1> 	;
  4266                              <1> 	; INPUT ->
  4267                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4268                              <1> 	;	[u.uno]
  4269                              <1> 	;	20/02/2017
  4270                              <1> 	;	(Linear address = CORE + user's virtual address)
  4271                              <1> 	;
  4272                              <1> 	; OUTPUT ->
  4273                              <1> 	;	EAX = [swpq_count]
  4274                              <1> 	;	      (after the PTE has been added)
  4275                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4276                              <1> 	;	      the PTE could not be added.
  4277                              <1> 	;
  4278                              <1> 	; Modified Registers -> EAX
  4279                              <1> 	;
  4280                              <1> ;	push	ebx
  4281                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4282                              <1> ;	mov	bl, [u.uno] ; current process number
  4283                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4284                              <1> ;				 ; it is already on the queue
  4285                              <1> ;		; then add it to the tail of the queue
  4286                              <1> ;	movzx	eax, word [swpq_count]
  4287                              <1> ;	cmp	ax, 1024
  4288                              <1> ;	jb	short atsq_1
  4289                              <1> ;	sub	ax, ax
  4290                              <1> ;	pop	ebx
  4291                              <1> ;	retn
  4292                              <1> ;atsq_1:
  4293                              <1> ;	push	esi
  4294                              <1> ;	mov	esi, swap_queue
  4295                              <1> ;	and	ax, ax
  4296                              <1> ;	jz	short atsq_2
  4297                              <1> ;	shl	ax, 2	; convert to offset
  4298                              <1> ;	add	esi, eax
  4299                              <1> ;	shr	ax, 2
  4300                              <1> ;atsq_2:
  4301                              <1> ;	inc	ax
  4302                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4303                              <1> ;	mov	[swpq_count], ax
  4304                              <1> ;	pop	esi
  4305                              <1> ;	pop	ebx
  4306                              <1> ;	retn
  4307                              <1> 
  4308                              <1> ; 24/12/2021
  4309                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4310                              <1> 
  4311                              <1> ;unlink_swap_block:
  4312                              <1> 	; 15/09/2015
  4313                              <1> 	; 30/04/2015
  4314                              <1> 	; 18/04/2015
  4315                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4316                              <1> 	;
  4317                              <1> 	; INPUT -> 
  4318                              <1> 	;	EAX = swap disk/file offset address
  4319                              <1> 	;	      (bit 1 to bit 31)
  4320                              <1> 	; OUTPUT ->
  4321                              <1> 	;	[swpd_free] is increased
  4322                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4323                              <1> 	;
  4324                              <1> 	; Modified Registers -> EAX
  4325                              <1> 	;
  4326                              <1> ;	push	ebx
  4327                              <1> ;	push	edx
  4328                              <1> ;	;
  4329                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4330                              <1> ;				     ; 3 bits right
  4331                              <1> ;				     ; to get swap block/page number
  4332                              <1> ;	mov	edx, eax
  4333                              <1> ;	; 15/09/2015
  4334                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4335                              <1> ;				     ; (1 allocation bit = 1 page)
  4336                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4337                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4338                              <1> ;				     ; (to get 32 bit position)			
  4339                              <1> ;	;
  4340                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4341                              <1> ;	add	ebx, edx
  4342                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4343                              <1> ;				     ; (allocation bit position)	 
  4344                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4345                              <1> ;				     ; than the address in 'swpd_next' ?
  4346                              <1> ;				     ; (next/first free block value)		
  4347                              <1> ;	jnb	short uswpbl_1	     ; no	
  4348                              <1> ;	mov	[swpd_next], eax     ; yes	
  4349                              <1> ;uswpbl_1:
  4350                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4351                              <1> ;				     ; set relevant bit to 1.
  4352                              <1> ;				     ; set CF to the previous bit value	
  4353                              <1> ;	cmc			     ; complement carry flag	
  4354                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4355                              <1> ;				     ; if the block is already deallocated
  4356                              <1> ;				     ; before.	
  4357                              <1> ;       inc     dword [swpd_free]
  4358                              <1> ;uswpbl_2:
  4359                              <1> ;	pop	edx
  4360                              <1> ;	pop	ebx
  4361                              <1> ;	retn
  4362                              <1> 
  4363                              <1> ; 24/12/2021
  4364                              <1> ; ('link_swap_block' procedure call is disabled)
  4365                              <1> 
  4366                              <1> ;link_swap_block:
  4367                              <1> 	; 01/07/2015
  4368                              <1> 	; 18/04/2015
  4369                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4370                              <1> 	;
  4371                              <1> 	; INPUT -> none
  4372                              <1> 	;
  4373                              <1> 	; OUTPUT ->
  4374                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4375                              <1> 	;	      in sectors (corresponding 
  4376                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4377                              <1> 	;
  4378                              <1> 	;	CF = 1 and EAX = 0 
  4379                              <1> 	; 		   if there is not a free block to be allocated	
  4380                              <1> 	;
  4381                              <1> 	; Modified Registers -> none (except EAX)
  4382                              <1> 	;
  4383                              <1> 
  4384                              <1> ;	;mov	eax, [swpd_free]
  4385                              <1> ;	;and	eax, eax
  4386                              <1> ;	;jz	short out_of_swpspc
  4387                              <1> ;	;
  4388                              <1> ;	push	ebx
  4389                              <1> ;	push	ecx
  4390                              <1> ;	;
  4391                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4392                              <1> ;	mov	ecx, ebx
  4393                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4394                              <1> ;				 ; next_free_swap_block >> 5
  4395                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4396                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4397                              <1> ;lswbl_scan:
  4398                              <1> ;	cmp	ebx, ecx
  4399                              <1> ;	ja	short lswbl_notfound
  4400                              <1> ;	;
  4401                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4402                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4403                              <1> ;			   ; loads the destination with an index to
  4404                              <1> ;			   ; first set bit. (0 -> 31) 
  4405                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4406                              <1> ;	; 01/07/2015
  4407                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4408                              <1> ;			 ;
  4409                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4410                              <1> ;			 ;	  with value of 1 means 
  4411                              <1> ;			 ;	  the corresponding page is free 
  4412                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4413                              <1> ;	add	ebx, 4
  4414                              <1> ;			 ; We return back for searching next page block
  4415                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4416                              <1> ;			 ;	 we always will find at least 1 free block here.
  4417                              <1> ;	jmp    	short lswbl_scan
  4418                              <1> ;	;
  4419                              <1> ;lswbl_notfound:	
  4420                              <1> ;	sub	ecx, swap_alloc_table
  4421                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4422                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4423                              <1> ;	xor	eax, eax
  4424                              <1> ;	mov	[swpd_free], eax
  4425                              <1> ;	stc
  4426                              <1> ;lswbl_ok:
  4427                              <1> ;	pop	ecx
  4428                              <1> ;	pop	ebx
  4429                              <1> ;	retn
  4430                              <1> ;	;
  4431                              <1> ;;out_of_swpspc:
  4432                              <1> ;;	stc
  4433                              <1> ;;	retn
  4434                              <1> ;
  4435                              <1> ;lswbl_found:
  4436                              <1> ;	mov	ecx, ebx
  4437                              <1> ;	sub	ecx, swap_alloc_table
  4438                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4439                              <1> ;				 ; address/offset (to the next)
  4440                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4441                              <1> ;	;
  4442                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4443                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4444                              <1> ;				 ; in the destination.
  4445                              <1> ;				 ;
  4446                              <1> ;				 ; Reset the bit which is corresponding to the 
  4447                              <1> ;				 ; (just) allocated block.
  4448                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4449                              <1> ;	add	eax, ecx	 ; = block number
  4450                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4451                              <1> ;				 ; 1 block =  8 sectors
  4452                              <1> ;	;
  4453                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4454                              <1> ;	;
  4455                              <1> ;	; NOTE: The relevant page table entry will be updated
  4456                              <1> ;	;       according to this EAX value...
  4457                              <1> ;	;
  4458                              <1> ;	jmp	short lswbl_ok
  4459                              <1> 
  4460                              <1> ; 24/12/2021
  4461                              <1> ; ('logical_disk_read' procedure call is disabled)
  4462                              <1> 
  4463                              <1> ;logical_disk_read:
  4464                              <1> 	; 20/07/2015
  4465                              <1> 	; 09/03/2015 (temporary code here)
  4466                              <1> 	;
  4467                              <1> 	; INPUT ->
  4468                              <1> 	; 	ESI = Logical disk description table address
  4469                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4470                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4471                              <1> 	; 	ECX = Sector count
  4472                              <1> 	;
  4473                              <1> 	;
  4474                              <1> ;	retn
  4475                              <1> 
  4476                              <1> ; 24/12/2021
  4477                              <1> ; ('logical_disk_write' procedure call is disabled)
  4478                              <1> 
  4479                              <1> ;logical_disk_write:
  4480                              <1> 	; 20/07/2015
  4481                              <1> 	; 09/03/2015 (temporary code here)
  4482                              <1> 	;
  4483                              <1> 	; INPUT ->
  4484                              <1> 	; 	ESI = Logical disk description table address
  4485                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4486                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4487                              <1> 	; 	ECX = Sector count
  4488                              <1> 	;
  4489                              <1> ;	retn
  4490                              <1> 
  4491                              <1> get_physical_addr:
  4492                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4493                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4494                              <1> 	; 18/10/2015
  4495                              <1> 	; 29/07/2015
  4496                              <1> 	; 20/07/2015
  4497                              <1> 	; 04/06/2015
  4498                              <1> 	; 20/05/2015
  4499                              <1> 	; 28/04/2015
  4500                              <1> 	; 18/04/2015
  4501                              <1> 	; Get physical address
  4502                              <1> 	;     (allocates a new page for user if it is not present)
  4503                              <1> 	;	
  4504                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4505                              <1> 	; (buffer) address to physical address (of the buffer).)
  4506                              <1> 	; ('sys write', 'sys read' system calls...)
  4507                              <1> 	;
  4508                              <1> 	; INPUT ->
  4509                              <1> 	;	EBX = virtual address
  4510                              <1> 	;	u.pgdir = page directory (physical) address
  4511                              <1> 	;
  4512                              <1> 	; OUTPUT ->
  4513                              <1> 	;	EAX = physical address 
  4514                              <1> 	;	EBX = linear address	
  4515                              <1> 	;	EDX = physical address of the page frame
  4516                              <1> 	;	      (with attribute bits)
  4517                              <1> 	;	ECX = byte count within the page frame
  4518                              <1> 	;
  4519                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4520                              <1> 	;
  4521                              <1> 
  4522                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4523 000028EC A1[63660000]        <1> 	mov	eax, [u.pgdir]
  4524                              <1> 
  4525                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4526                              <1> 	
  4527 000028F1 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4528                              <1> 	;
  4529                              <1> 	;mov	eax, [u.pgdir]
  4530 000028F7 E816FDFFFF          <1> 	call	get_pte
  4531                              <1> 		; EDX = Page table entry address (if CF=0)
  4532                              <1> 	        ;       Page directory entry address (if CF=1)
  4533                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4534                              <1> 		; EAX = Page table entry value (page address)
  4535                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4536 000028FC 731C                <1> 	jnc	short gpa_1
  4537                              <1> 	;
  4538 000028FE E8FDFBFFFF          <1> 	call	allocate_page
  4539 00002903 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4540                              <1> gpa_0:
  4541 00002905 E867FCFFFF          <1> 	call 	clear_page
  4542                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4543 0000290A 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4544                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4545                              <1> 			   ; (user, writable, present page)	
  4546 0000290C 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4547 0000290E A1[63660000]        <1> 	mov	eax, [u.pgdir]	
  4548 00002913 E8FAFCFFFF          <1> 	call	get_pte
  4549 00002918 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4550                              <1> gpa_1:
  4551                              <1> 	; EAX = PTE value, EDX = PTE address
  4552 0000291A A801                <1> 	test 	al, PTE_A_PRESENT
  4553 0000291C 750A                <1> 	jnz	short gpa_3
  4554 0000291E 09C0                <1> 	or	eax, eax
  4555 00002920 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4556                              <1> 
  4557                              <1> ; 24/12/2021
  4558                              <1> ; ('reload_page' procedure call is disabled)
  4559 00002922 EB2C                <1> 	jmp	short gpa_im_err
  4560                              <1> 
  4561                              <1> 	; 20/07/2015
  4562                              <1> ;	push	ebp
  4563                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4564                              <1> ;	; reload swapped page
  4565                              <1> ;	call	reload_page ; 28/04/2015
  4566                              <1> ;	pop	ebp
  4567                              <1> ;	jc	short gpa_retn
  4568                              <1> gpa_2:
  4569                              <1> ; 24/12/2021
  4570                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4571                              <1> 
  4572                              <1> 	; 20/07/2015
  4573                              <1> 	; 20/05/2015
  4574                              <1> 	; add this page to swap queue
  4575                              <1> ;	push	eax 
  4576                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4577                              <1> ;	call 	add_to_swap_queue
  4578                              <1> ;	pop	eax
  4579                              <1> 		; PTE address in EDX
  4580                              <1> 		; virtual address in EBX
  4581                              <1> 	; EAX = memory page address
  4582 00002924 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4583                              <1> 				  ; present flag, bit 0 = 1
  4584                              <1> 				  ; user flag, bit 2 = 1	
  4585                              <1> 				  ; writable flag, bit 1 = 1
  4586 00002926 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4587                              <1> gpa_3:
  4588                              <1> 	; 18/10/2015
  4589 00002928 89D9                <1> 	mov	ecx, ebx
  4590 0000292A 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4591 00002930 89C2                <1> 	mov 	edx, eax
  4592 00002932 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4593 00002936 01C8                <1> 	add	eax, ecx
  4594 00002938 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4595 0000293A 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4596 00002940 F8                  <1> 	clc
  4597                              <1> gpa_retn:
  4598 00002941 C3                  <1> 	retn	
  4599                              <1> gpa_4:	
  4600 00002942 E8B9FBFFFF          <1> 	call	allocate_page
  4601 00002947 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4602 00002949 E823FCFFFF          <1> 	call	clear_page
  4603 0000294E EBD4                <1> 	jmp	short gpa_2
  4604                              <1> 
  4605                              <1> gpa_im_err:	
  4606 00002950 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4607                              <1> 				  ; Major error = 0 (No protection fault)	
  4608 00002955 C3                  <1> 	retn
  4609                              <1> 
  4610                              <1> ; 24/12/2021
  4611                              <1> ; ('reload_page' procedure call is disabled)
  4612                              <1> 
  4613                              <1> ;reload_page:
  4614                              <1> 	; 20/07/2015
  4615                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4616                              <1> 	;
  4617                              <1> 	; Reload (Restore) swapped page at memory
  4618                              <1> 	;
  4619                              <1> 	; INPUT -> 
  4620                              <1> 	;	EBP = Virtual (linear) memory address
  4621                              <1> 	;	EAX = PTE value (swap disk sector address)
  4622                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4623                              <1> 	; OUTPUT ->
  4624                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4625                              <1> 	;
  4626                              <1> 	;	CF = 1 and EAX = error code
  4627                              <1> 	;
  4628                              <1> 	; Modified Registers -> none (except EAX)
  4629                              <1> 	;
  4630                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4631                              <1> ;	push	ebx      ;
  4632                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4633                              <1> ;	call	allocate_page
  4634                              <1> ;	jc	short rlp_im_err
  4635                              <1> ;	xchg 	eax, ebx	
  4636                              <1> ;	; EBX = Physical memory (page) address
  4637                              <1> ;	; EAX = Swap disk (offset) address
  4638                              <1> ;	; EBP = Virtual (linear) memory address
  4639                              <1> ;	call	swap_in
  4640                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4641                              <1> ;	mov	eax, ebx	
  4642                              <1> ;rlp_retn:
  4643                              <1> ;	pop	ebx
  4644                              <1> ;	retn
  4645                              <1> ;	
  4646                              <1> ;rlp_im_err:	
  4647                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4648                              <1> ;				  ; Major error = 0 (No protection fault)	
  4649                              <1> ;	jmp	short rlp_retn
  4650                              <1> ;
  4651                              <1> ;rlp_swp_err:
  4652                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4653                              <1> ;	jmp	short rlp_retn
  4654                              <1> 
  4655                              <1> copy_page_dir:
  4656                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4657                              <1> 	; 19/09/2015
  4658                              <1> 	; temporary - 07/09/2015
  4659                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4660                              <1> 	;
  4661                              <1> 	; INPUT -> 
  4662                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4663                              <1> 	;		    page directory.
  4664                              <1> 	; OUTPUT ->
  4665                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4666                              <1> 	;	       page directory.
  4667                              <1> 	;	(New page directory with new page table entries.)
  4668                              <1> 	;	(New page tables with read only copies of the parent's
  4669                              <1> 	;	pages.)
  4670                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4671                              <1> 	;
  4672                              <1> 	; Modified Registers -> none (except EAX)
  4673                              <1> 	;
  4674 00002956 E8A5FBFFFF          <1> 	call	allocate_page
  4675 0000295B 723E                <1> 	jc	short cpd_err
  4676                              <1> 	;
  4677 0000295D 55                  <1> 	push	ebp ; 20/07/2015
  4678 0000295E 56                  <1> 	push	esi
  4679 0000295F 57                  <1> 	push	edi
  4680 00002960 53                  <1> 	push	ebx
  4681 00002961 51                  <1> 	push	ecx
  4682 00002962 8B35[63660000]      <1> 	mov	esi, [u.pgdir]
  4683 00002968 89C7                <1> 	mov	edi, eax
  4684 0000296A 50                  <1> 	push	eax ; save child's page directory address
  4685                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4686                              <1> 	; (use same system space for all user page tables) 
  4687 0000296B A5                  <1> 	movsd
  4688 0000296C BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4689 00002971 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4690                              <1> cpd_0:	
  4691 00002976 AD                  <1> 	lodsd
  4692                              <1> 	;or	eax, eax
  4693                              <1>         ;jnz	short cpd_1
  4694 00002977 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4695 00002979 7508                <1> 	jnz	short cpd_1
  4696                              <1>  	; (virtual address at the end of the page table)	
  4697 0000297B 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4698 00002981 EB0F                <1> 	jmp	short cpd_2
  4699                              <1> cpd_1:	
  4700 00002983 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4701 00002987 89C3                <1> 	mov	ebx, eax
  4702                              <1> 	; EBX = Parent's page table address
  4703 00002989 E81F000000          <1> 	call	copy_page_table
  4704 0000298E 720C                <1> 	jc	short cpd_p_err
  4705                              <1> 	; EAX = Child's page table address
  4706 00002990 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4707                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4708                              <1> 			 ; (present, writable, user)
  4709                              <1> cpd_2:
  4710 00002992 AB                  <1> 	stosd
  4711 00002993 E2E1                <1> 	loop	cpd_0
  4712                              <1> 	;
  4713 00002995 58                  <1> 	pop	eax  ; restore child's page directory address
  4714                              <1> cpd_3:
  4715 00002996 59                  <1> 	pop	ecx
  4716 00002997 5B                  <1> 	pop	ebx
  4717 00002998 5F                  <1> 	pop	edi
  4718 00002999 5E                  <1> 	pop	esi
  4719 0000299A 5D                  <1> 	pop	ebp
  4720                              <1> cpd_err:
  4721 0000299B C3                  <1> 	retn
  4722                              <1> cpd_p_err:
  4723                              <1> 	; release the allocated pages missing (recover free space)
  4724 0000299C 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4725 0000299D 8B1D[63660000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4726 000029A3 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4727 000029A8 29C0                <1> 	sub	eax, eax ; 0
  4728 000029AA F9                  <1> 	stc
  4729 000029AB EBE9                <1> 	jmp	short cpd_3	
  4730                              <1> 
  4731                              <1> copy_page_table:
  4732                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4733                              <1> 	; 19/09/2015
  4734                              <1> 	; temporary - 07/09/2015
  4735                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4736                              <1> 	;
  4737                              <1> 	; INPUT -> 
  4738                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4739                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4740                              <1> 	; OUTPUT ->
  4741                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4742                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4743                              <1> 	;	CF = 1 -> error 
  4744                              <1> 	;
  4745                              <1> 	; Modified Registers -> EBP (except EAX)
  4746                              <1> 	;
  4747 000029AD E84EFBFFFF          <1> 	call	allocate_page
  4748 000029B2 7244                <1> 	jc	short cpt_err
  4749                              <1> 	;
  4750 000029B4 50                  <1> 	push	eax ; *
  4751                              <1> 	;push 	ebx
  4752 000029B5 56                  <1> 	push	esi
  4753 000029B6 57                  <1> 	push	edi
  4754 000029B7 52                  <1> 	push	edx
  4755 000029B8 51                  <1> 	push	ecx
  4756                              <1> 	;
  4757 000029B9 89DE                <1> 	mov	esi, ebx
  4758 000029BB 89C7                <1> 	mov	edi, eax
  4759 000029BD 89C2                <1> 	mov	edx, eax
  4760 000029BF 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4761                              <1> cpt_0:
  4762 000029C5 AD                  <1> 	lodsd
  4763 000029C6 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4764                              <1> 	;jnz	short cpt_1 (*)
  4765                              <1> 	; 24/12/2021
  4766                              <1> 	;and	eax, eax (*)
  4767 000029C8 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4768                              <1> 	
  4769                              <1> ; 24/12/2021
  4770                              <1> ; ('reload_page' procedure call is disabled)
  4771                              <1> ;
  4772                              <1> ;	; ebp = virtual (linear) address of the memory page
  4773                              <1> ;	call	reload_page ; 28/04/2015
  4774                              <1> ;	jc	short cpt_p_err
  4775                              <1> cpt_1:
  4776 000029CA 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4777 000029CE 89C1                <1> 	mov	ecx, eax
  4778                              <1> 	; Allocate a new page for the child process
  4779 000029D0 E82BFBFFFF          <1> 	call	allocate_page
  4780 000029D5 721C                <1> 	jc	short cpt_p_err
  4781 000029D7 57                  <1> 	push	edi
  4782 000029D8 56                  <1> 	push	esi
  4783 000029D9 89CE                <1> 	mov	esi, ecx
  4784 000029DB 89C7                <1> 	mov	edi, eax
  4785 000029DD B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4786 000029E2 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4787 000029E4 5E                  <1> 	pop	esi
  4788 000029E5 5F                  <1> 	pop	edi
  4789                              <1> 	; 
  4790                              <1> ; 24/12/2021
  4791                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4792                              <1> ;
  4793                              <1> ;	push	ebx
  4794                              <1> ;	push	eax
  4795                              <1> ;	mov	ebx, ebp
  4796                              <1> ;	; ebx = virtual address of the memory page
  4797                              <1> ;	call	add_to_swap_queue
  4798                              <1> ;	pop	eax
  4799                              <1> ;	pop	ebx
  4800                              <1> 	;
  4801                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4802 000029E6 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4803                              <1> cpt_2:
  4804 000029E8 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4805                              <1> 	;
  4806 000029E9 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4807                              <1> 	;
  4808 000029EF 39D7                <1> 	cmp	edi, edx
  4809 000029F1 72D2                <1> 	jb	short cpt_0
  4810                              <1> cpt_p_err:
  4811 000029F3 59                  <1> 	pop	ecx
  4812 000029F4 5A                  <1> 	pop	edx
  4813 000029F5 5F                  <1> 	pop	edi
  4814 000029F6 5E                  <1> 	pop	esi
  4815                              <1> 	;pop	ebx
  4816 000029F7 58                  <1> 	pop	eax ; *
  4817                              <1> cpt_err:
  4818 000029F8 C3                  <1> 	retn
  4819                              <1> 
  4820                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4821                              <1> 
  4822                              <1> ;; Data:
  4823                              <1> 
  4824                              <1> ; 09/03/2015
  4825                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4826                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4827                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4828                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4829                              <1> ;swpd_next:  dd 0 ; next free page block
  4830                              <1> ;swpd_last:  dd 0 ; last swap page block
  2048                                  %include 'sysdefs.inc' ; 09/03/2015
  2049                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYSDEFS.INC
  2050                              <1> ; Last Modification: 15/07/2022
  2051                              <1> ;
  2052                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2053                              <1> ; (Modified from 
  2054                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2055                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2056                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2057                              <1> ; ----------------------------------------------------------------------------
  2058                              <1> ;
  2059                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2060                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2061                              <1> ; <Bell Laboratories (17/3/1972)>
  2062                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2063                              <1> ;
  2064                              <1> ; ****************************************************************************
  2065                              <1> 
  2066                              <1> nproc 	equ	16  ; number of processes
  2067                              <1> nfiles 	equ	50
  2068                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2069                              <1> ;nbuf	equ	6   ; number of buffers (04/02/2016)
  2070                              <1> nbuf	equ	8   ; 15/07/2022	  	
  2071                              <1> 
  2072                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2073                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2074                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2075                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2076                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2077                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2078                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2079                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2080                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2081                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2082                              <1> 	; '/core' dump file size = 32768 bytes
  2083                              <1>  
  2084                              <1> ; 08/03/2014 
  2085                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2086                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feature only !
  2087                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2088                              <1> 
  2089                              <1> ; 30/08/2013
  2090                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2091                              <1> 
  2092                              <1> ; 05/02/2014
  2093                              <1> ; process status
  2094                              <1> ;SFREE 	equ 0
  2095                              <1> ;SRUN	equ 1
  2096                              <1> ;SWAIT	equ 2
  2097                              <1> ;SZOMB	equ 3
  2098                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2099                              <1> 
  2100                              <1> ; 09/03/2015
  2101                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2102                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2103                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2104                              <1> 
  2105                              <1> ; 17/09/2015
  2106                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2107                              <1> 
  2108                              <1> ; 21/09/2015 (36) 
  2109                              <1> ; 01/07/2015 (35)
  2110                              <1> ; 14/07/2013 (0-34)
  2111                              <1> ; UNIX v1 system calls
  2112                              <1> _rele 	equ 0
  2113                              <1> _exit 	equ 1
  2114                              <1> _fork 	equ 2
  2115                              <1> _read 	equ 3
  2116                              <1> _write	equ 4
  2117                              <1> _open	equ 5
  2118                              <1> _close 	equ 6
  2119                              <1> _wait 	equ 7
  2120                              <1> _creat 	equ 8
  2121                              <1> _link 	equ 9
  2122                              <1> _unlink	equ 10
  2123                              <1> _exec	equ 11
  2124                              <1> _chdir	equ 12
  2125                              <1> _time 	equ 13
  2126                              <1> _mkdir 	equ 14
  2127                              <1> _chmod	equ 15
  2128                              <1> _chown	equ 16
  2129                              <1> _break	equ 17
  2130                              <1> _stat	equ 18
  2131                              <1> _seek	equ 19
  2132                              <1> _tell 	equ 20
  2133                              <1> _mount	equ 21
  2134                              <1> _umount	equ 22
  2135                              <1> _setuid	equ 23
  2136                              <1> _getuid	equ 24
  2137                              <1> _stime	equ 25
  2138                              <1> _quit	equ 26	
  2139                              <1> _intr	equ 27
  2140                              <1> _fstat	equ 28
  2141                              <1> _emt 	equ 29
  2142                              <1> _mdate 	equ 30
  2143                              <1> _stty 	equ 31
  2144                              <1> _gtty	equ 32
  2145                              <1> _ilgins	equ 33
  2146                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2147                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2148                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2149                              <1> 
  2150                              <1> %macro sys 1-4
  2151                              <1>     ; 13/04/2015
  2152                              <1>     ; Retro UNIX 386 v1 system call.		
  2153                              <1>     mov eax, %1
  2154                              <1>     %if %0 >= 2   
  2155                              <1>         mov ebx, %2
  2156                              <1>         %if %0 >= 3    
  2157                              <1>             mov ecx, %3
  2158                              <1>             %if %0 = 4
  2159                              <1>                mov edx, %4   
  2160                              <1>             %endif
  2161                              <1>         %endif
  2162                              <1>     %endif
  2163                              <1>     int 30h	   
  2164                              <1> %endmacro
  2165                              <1> 
  2166                              <1> ; 13/05/2015 - ERROR CODES
  2167                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2168                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2169                              <1> ; 14/05/2015
  2170                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2171                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2172                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2173                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2174                              <1> ; 16/05/2015		
  2175                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2176                              <1> ; 18/05/2015
  2177                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2178                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2179                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2180                              <1> ; 07/06/2015
  2181                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2182                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2183                              <1> ; 09/06/2015
  2184                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2185                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2186                              <1> ; 16/06/2015
  2187                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2188                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2189                              <1> ; 22/06/2015
  2190                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2191                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2192                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2193                              <1> ; 23/06/2015
  2194                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2195                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2196                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2197                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2198                              <1> ; 27/06/2015
  2199                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2200                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2201                              <1> ; 29/06/2015
  2202                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2203                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2204                              <1> ; 12/02/2022 
  2205                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2206                              <1> ; 10/10/2016
  2207                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2208                              <1> ; 18/05/2016
  2209                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2210                              <1> ; 15/10/2016
  2211                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2212                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2213                              <1> ; 16/10/2016
  2214                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2215                              <1> ; 08/02/2022
  2216                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2217                              <1> 
  2218                              <1> ; 13/06/2022
  2219                              <1> ; printer errors
  2220                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2221                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2222                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2223                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2224                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error	
  2225                              <1> 
  2226                              <1> ; 26/08/2015
  2227                              <1> ; 24/07/2015
  2228                              <1> ; 24/06/2015
  2229                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2230                              <1> ; 01/07/2015
  2231                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2232                              <1> ;	 					 		
  2049                                  %include 'u0.s'        ; 15/03/2015
  2050                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS0.INC
  2051                              <1> ; Last Modification: 02/06/2022
  2052                              <1> ; ----------------------------------------------------------------------------
  2053                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2054                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2055                              <1> ;
  2056                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2057                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2058                              <1> ; <Bell Laboratories (17/3/1972)>
  2059                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2060                              <1> ;
  2061                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2062                              <1> ;
  2063                              <1> ; ****************************************************************************
  2064                              <1> ; 21/11/2015
  2065                              <1> 
  2066                              <1> sys_init:
  2067                              <1> 	; 27/02/2022
  2068                              <1> 	; 23/02/2022
  2069                              <1> 	; 04/02/2022
  2070                              <1> 	; 18/10/2015
  2071                              <1> 	; 28/08/2015
  2072                              <1> 	; 24/08/2015
  2073                              <1> 	; 14/08/2015
  2074                              <1> 	; 24/07/2015 
  2075                              <1> 	; 02/07/2015
  2076                              <1> 	; 01/07/2015
  2077                              <1> 	; 23/06/2015
  2078                              <1> 	; 15/04/2015
  2079                              <1> 	; 13/04/2015
  2080                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2081                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2082                              <1> 	;
  2083                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2084                              <1> 	;
  2085                              <1> 	; 14/02/2014
  2086                              <1> 	; 14/07/2013
  2087                              <1> 	;;mov	ax, 41
  2088                              <1> 	; 27/02/2022
  2089                              <1> 	;xor	eax, eax
  2090                              <1> 	;mov	al, 41
  2091                              <1> 	;mov	[rootdir], ax
  2092                              <1> 	;mov	[u.cdir], ax
  2093                              <1> 	;;and	al, 1 ; 15/04/2015
  2094                              <1> 	;inc	al  ; ax = 1
  2095 000029F9 B001                <1> 	mov	al, 1
  2096 000029FB A2[59660000]        <1> 	mov	[u.uno], al
  2097                              <1> 	;mov	[mpid], ax
  2098                              <1> 	;mov	[p.pid], ax
  2099 00002A00 A2[FC650000]        <1> 	mov	[mpid], al
  2100 00002A05 A2[24630000]        <1> 	mov	[p.pid], al	
  2101 00002A0A A2[84630000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2102                              <1> 	; 27/02/2022
  2103 00002A0F B029                <1> 	mov	al, 41
  2104                              <1> 	;mov	[rootdir], ax
  2105                              <1> 	;mov	[u.cdir], ax
  2106 00002A11 A2[FE650000]        <1> 	mov	[rootdir], al
  2107 00002A16 A2[14660000]        <1> 	mov	[u.cdir], al
  2108                              <1> 	;
  2109                              <1> 	; 23/02/2022
  2110                              <1>  	;call	epoch
  2111                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2112                              <1> 	; 17/07/2013
  2113 00002A1B E88B060000          <1> 	call 	bf_init ; buffer initialization
  2114                              <1> 	; 23/02/2022
  2115                              <1> 	; (save sysinit time on sb0)
  2116 00002A20 E830030000          <1> 	call	epoch
  2117 00002A25 A3[64780000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2118                              <1> 	; 23/06/2015
  2119 00002A2A E8D1FAFFFF          <1> 	call	allocate_page
  2120                              <1> 	;;jc	error
  2121                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2122                              <1> 	; 04/02/2022
  2123 00002A2F 7305                <1> 	jnc	short sysinit_1
  2124 00002A31 E990000000          <1> 	jmp	panic
  2125                              <1> sysinit_1:
  2126 00002A36 A3[5A660000]        <1> 	mov	[u.upage], eax ; user structure page	
  2127 00002A3B A3[94630000]        <1> 	mov	[p.upage], eax
  2128                              <1> 	;
  2129 00002A40 E82CFBFFFF          <1> 	call	clear_page
  2130                              <1> 	;
  2131                              <1> 	; 14/08/2015
  2132 00002A45 FA                  <1> 	cli
  2133                              <1> 	; 14/03/2015
  2134                              <1> 	; 17/01/2014
  2135 00002A46 E8D7010000          <1> 	call	sp_init ; serial port initialization
  2136                              <1> 	; 14/08/2015
  2137 00002A4B FB                  <1> 	sti
  2138                              <1> 	;
  2139                              <1> 	; 30/06/2015
  2140                              <1> 	;mov	esi, kernel_init_ok_msg
  2141                              <1> 	;call 	print_msg
  2142                              <1> 	;
  2143 00002A4C 30DB                <1> 	xor	bl, bl ; video page 0
  2144                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2145 00002A4E E8400F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2146 00002A53 FEC3                <1> 	inc	bl
  2147 00002A55 80FB08              <1> 	cmp	bl, 8
  2148 00002A58 72F4                <1> 	jb	short vp_clr_nxt
  2149                              <1> 	;
  2150                              <1> 	; 24/07/2015
  2151                              <1> 	;push	KDATA
  2152                              <1>         ;push	esp
  2153                              <1> 	;mov	[tss.esp0], esp
  2154                              <1>         ;mov	word [tss.ss0], KDATA
  2155                              <1> 	;
  2156                              <1> 	; 27/02/2022
  2157                              <1> 	; 24/08/2015
  2158                              <1> 	;; temporary (01/07/2015)
  2159                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2160                              <1> 			       ; it is not needed here !
  2161                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2162 00002A5A FE0D[05660000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2163                              <1> 			      ; 0 = executing a system call
  2164                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2165                              <1> 	;
  2166                              <1> 	;;; 06/08/2015
  2167                              <1> 	;;;call	getch ; wait for a key stroke
  2168                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2169                              <1> ;;sys_init_msg_wait:
  2170                              <1> ;;	push 	ecx
  2171                              <1> ;;	mov	al, 1
  2172                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2173                              <1> ;;	call	getc_n
  2174                              <1> ;;	pop	ecx
  2175                              <1> ;;	jnz	short sys_init_msg_ok
  2176                              <1> ;;	loop	sys_init_msg_wait
  2177                              <1> 	;
  2178                              <1> ;;sys_init_msg_ok:
  2179                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2180 00002A60 6A10                <1> 	push	KDATA ; ss
  2181 00002A62 54                  <1> 	push	esp
  2182 00002A63 9C                  <1> 	pushfd
  2183 00002A64 6A08                <1> 	push	KCODE ; cs
  2184 00002A66 68[9A2A0000]        <1> 	push	init_exec ; eip
  2185 00002A6B 8925[08660000]      <1> 	mov	[u.sp], esp
  2186 00002A71 1E                  <1> 	push	ds
  2187 00002A72 06                  <1> 	push	es
  2188 00002A73 0FA0                <1> 	push	fs
  2189 00002A75 0FA8                <1> 	push	gs	
  2190 00002A77 60                  <1> 	pushad
  2191 00002A78 8925[0C660000]      <1> 	mov	[u.usp], esp
  2192 00002A7E E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2193                              <1> 		      ; and interrupt return components (for IRET)
  2194 00002A83 61                  <1> 	popad
  2195 00002A84 6658                <1> 	pop	ax ; gs
  2196 00002A86 6658                <1> 	pop	ax ; fs
  2197 00002A88 6658                <1> 	pop	ax ; es
  2198 00002A8A 6658                <1> 	pop	ax ; ds	
  2199 00002A8C 58                  <1> 	pop	eax ; eip (init_exec)
  2200 00002A8D 6658                <1> 	pop	ax ; cs (KCODE)
  2201 00002A8F 58                  <1> 	pop	eax ; E-FLAGS
  2202 00002A90 58                  <1> 	pop	eax ; esp
  2203 00002A91 6658                <1> 	pop	ax ; ss (KDATA)
  2204                              <1> 	;
  2205 00002A93 31C0                <1> 	xor	eax, eax ; 0
  2206 00002A95 A3[67660000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2207                              <1> 	;
  2208                              <1> 	; 02/07/2015
  2209                              <1> 	; [u.pgdir ] = [k_page_dir]
  2210                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2211                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2212                              <1> init_exec:
  2213                              <1> 	; 13/03/2013
  2214                              <1> 	; 24/07/2013
  2215 00002A9A BB[BC2A0000]        <1> 	mov	ebx, init_file
  2216 00002A9F B9[B42A0000]        <1> 	mov	ecx, init_argp
  2217                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2218                              <1> 	; ECX contains address of argument list pointer
  2219                              <1> 	;
  2220                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2221                              <1> 			      ; 0 = executing a system call
  2222                              <1> 	sys	_exec  ; execute file
  2151                              <2> 
  2152                              <2> 
  2153 00002AA4 B80B000000          <2>  mov eax, %1
  2154                              <2>  %if %0 >= 2
  2155                              <2>  mov ebx, %2
  2156                              <2>  %if %0 >= 3
  2157                              <2>  mov ecx, %3
  2158                              <2>  %if %0 = 4
  2159                              <2>  mov edx, %4
  2160                              <2>  %endif
  2161                              <2>  %endif
  2162                              <2>  %endif
  2163 00002AA9 CD30                <2>  int 30h
  2223 00002AAB 7319                <1> 	jnc	short panic
  2224                              <1> 	;
  2225 00002AAD BE[5E5F0000]        <1> 	mov	esi, etc_init_err_msg
  2226                              <1> 	; 27/02/2022
  2227                              <1> 	;call 	print_msg
  2228 00002AB2 EB17                <1> 	jmp	short key_to_reboot
  2229                              <1> 
  2230                              <1> ;align 4
  2231                              <1> init_argp:
  2232 00002AB4 [BC2A0000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2233                              <1> init_file:
  2234                              <1> 	; 24/08/2015
  2235 00002ABC 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2235 00002AC5 00                  <1>
  2236                              <1> panic:
  2237                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2238                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2239 00002AC6 BE[435F0000]        <1> 	mov 	esi, panic_msg
  2240                              <1> key_to_reboot: ; 27/02/2022
  2241 00002ACB E819000000          <1> 	call 	print_msg
  2242                              <1> ;key_to_reboot:
  2243                              <1> 	; 15/11/2015
  2244 00002AD0 E8C32B0000          <1> 	call 	getch 
  2245                              <1> 		; wait for a character from the current tty
  2246                              <1> 	;
  2247 00002AD5 B00A                <1> 	mov	al, 0Ah
  2248 00002AD7 8A1D[76620000]      <1> 	mov	bl, [ptty] ; [active_page]
  2249 00002ADD B407                <1> 	mov	ah, 07h ; Black background, 
  2250                              <1> 			; light gray forecolor
  2251 00002ADF E8D8E8FFFF          <1> 	call 	write_tty
  2252 00002AE4 E977E5FFFF          <1> 	jmp	cpu_reset 
  2253                              <1> 
  2254                              <1> print_msg:
  2255                              <1> 	; 01/07/2015
  2256                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2257                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2258                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2259                              <1> 	;
  2260                              <1> 	;
  2261 00002AE9 AC                  <1> 	lodsb
  2262                              <1> pmsg1:
  2263 00002AEA 56                  <1> 	push 	esi
  2264 00002AEB 0FB61D[76620000]    <1> 	movzx	ebx, byte [ptty]
  2265 00002AF2 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2266 00002AF4 E8C3E8FFFF          <1> 	call 	write_tty
  2267 00002AF9 5E                  <1> 	pop	esi
  2268 00002AFA AC                  <1> 	lodsb
  2269 00002AFB 20C0                <1> 	and 	al, al
  2270 00002AFD 75EB                <1> 	jnz 	short pmsg1
  2271 00002AFF C3                  <1> 	retn
  2272                              <1> 	
  2273                              <1> ctrlbrk:
  2274                              <1> 	; 04/02/2022
  2275                              <1> 	; 01/02/2022
  2276                              <1> 	; 12/11/2015
  2277                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2278                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2279                              <1> 	;
  2280                              <1> 	; INT 1Bh (control+break) handler
  2281                              <1> 	;
  2282                              <1>       	; Retro Unix 8086 v1 feature only!
  2283                              <1>       	;
  2284 00002B00 66833D[4E660000]00  <1> 	cmp 	word [u.intr], 0
  2285 00002B08 764B                <1> 	jna 	short cbrk4
  2286                              <1> cbrk0:
  2287                              <1> 	; 12/11/2015
  2288                              <1> 	; 06/12/2013
  2289 00002B0A 66833D[50660000]00  <1> 	cmp 	word [u.quit], 0
  2290 00002B12 7441                <1> 	jz	short cbrk4
  2291                              <1> 	;
  2292                              <1> 	; 20/09/2013	
  2293                              <1> 	;push 	ax
  2294                              <1> 	; 01/02/2022
  2295 00002B14 50                  <1> 	push	eax
  2296                              <1> 
  2297                              <1> 	; 04/02/2022
  2298                              <1> 	; (repetitive ctrl+brk check) 
  2299 00002B15 66A1[50660000]      <1> 	mov	ax, [u.quit]
  2300 00002B1B 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2301 00002B1D 7435                <1> 	jz	short cbrk3
  2302                              <1> 
  2303                              <1> 	; 20/09/2013
  2304 00002B1F A0[76620000]        <1> 	mov	al, [ptty]
  2305                              <1> 	;
  2306                              <1> 	; 12/11/2015
  2307                              <1> 	;
  2308                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2309                              <1> 	; or ctrl+break from console (pseudo) tty
  2310                              <1> 	; (!redirection!)
  2311                              <1> 	;
  2312 00002B24 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2313 00002B26 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2314                              <1> 	;	
  2315                              <1> 	; Serial port interrupt handler sets [ptty]
  2316                              <1> 	; to the port's tty number (as temporary).
  2317                              <1> 	;
  2318                              <1> 	; If active process is using a stdin or 
  2319                              <1> 	; stdout redirection (by the shell),
  2320                              <1>         ; console tty keyboard must be available
  2321                              <1> 	; to terminate running process,
  2322                              <1> 	; in order to prevent a deadlock. 
  2323                              <1> 	;
  2324 00002B28 52                  <1> 	push	edx
  2325 00002B29 0FB615[59660000]    <1> 	movzx	edx, byte [u.uno]
  2326 00002B30 3A82[63630000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2327 00002B36 5A                  <1> 	pop	edx
  2328 00002B37 7412                <1> 	je	short cbrk2
  2329                              <1> cbrk1:
  2330 00002B39 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2331                              <1> 	; 06/12/2013
  2332 00002B3B 3A05[40660000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2333 00002B41 7408                <1> 	je	short cbrk2	
  2334 00002B43 3A05[41660000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2335 00002B49 7509                <1> 	jne	short cbrk3	
  2336                              <1> cbrk2:
  2337                              <1> 	;; 06/12/2013
  2338                              <1> 	;mov	ax, [u.quit]
  2339                              <1> 	;and	ax, ax
  2340                              <1> 	;jz	short cbrk3
  2341                              <1> 	;
  2342                              <1> 	;xor	ax, ax ; 0
  2343                              <1> 	;dec	ax
  2344                              <1> 	; 01/02/2022
  2345 00002B4B 31C0                <1> 	xor	eax, eax ; 0
  2346 00002B4D 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2347                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2348 00002B4E 66A3[50660000]      <1> 	mov	[u.quit], ax
  2349                              <1> cbrk3:
  2350                              <1> 	;pop	ax
  2351                              <1> 	; 01/02/2022
  2352 00002B54 58                  <1> 	pop	eax
  2353                              <1> cbrk4:
  2354 00002B55 C3                  <1> 	retn
  2355                              <1> 
  2356                              <1> com2_int:
  2357                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2358                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2359                              <1> 	; 07/11/2015 
  2360                              <1> 	; 24/10/2015
  2361                              <1> 	; 23/10/2015
  2362                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2363                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2364                              <1> 	; < serial port 2 interrupt handler >
  2365                              <1> 	;
  2366 00002B56 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2367                              <1> 	;;push	eax
  2368                              <1> 	; 08/01/2022
  2369 00002B59 29C0                <1> 	sub	eax, eax
  2370 00002B5B B009                <1> 	mov	al, 9
  2371                              <1> 	;mov	ax, 9
  2372 00002B5D EB07                <1> 	jmp	short comm_int
  2373                              <1> com1_int:
  2374                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2375                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2376                              <1> 	; 07/11/2015
  2377                              <1> 	; 24/10/2015
  2378 00002B5F 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2379                              <1> 	; 23/10/2015
  2380                              <1> 	;push	eax
  2381                              <1> 	; 08/01/2022
  2382 00002B62 29C0                <1> 	sub	eax, eax
  2383 00002B64 B008                <1> 	mov	al, 8
  2384                              <1> 	;mov	ax, 8
  2385                              <1> comm_int:
  2386                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2387                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2388                              <1> 	; 20/11/2015
  2389                              <1> 	; 18/11/2015
  2390                              <1> 	; 17/11/2015
  2391                              <1> 	; 16/11/2015
  2392                              <1> 	; 09/11/2015
  2393                              <1> 	; 08/11/2015
  2394                              <1> 	; 07/11/2015
  2395                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2396                              <1> 	; 01/11/2015
  2397                              <1> 	; 26/10/2015
  2398                              <1> 	; 23/10/2015
  2399 00002B66 53                  <1> 	push	ebx
  2400 00002B67 56                  <1> 	push	esi
  2401 00002B68 57                  <1> 	push	edi
  2402 00002B69 1E                  <1> 	push 	ds
  2403 00002B6A 06                  <1> 	push 	es
  2404                              <1> 	; 18/11/2015
  2405 00002B6B 0F20DB              <1> 	mov	ebx, cr3
  2406 00002B6E 53                  <1> 	push	ebx ; ****
  2407                              <1> 	;
  2408 00002B6F 51                  <1> 	push	ecx ; ***
  2409 00002B70 52                  <1> 	push	edx ; **
  2410                              <1> 	;
  2411 00002B71 BB10000000          <1> 	mov	ebx, KDATA
  2412 00002B76 8EDB                <1> 	mov	ds, bx
  2413 00002B78 8EC3                <1> 	mov	es, bx
  2414                              <1> 	;
  2415 00002B7A 8B0D[48620000]      <1> 	mov	ecx, [k_page_dir]
  2416 00002B80 0F22D9              <1> 	mov	cr3, ecx
  2417                              <1> 	; 20/11/2015
  2418                              <1> 	; Interrupt identification register
  2419 00002B83 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2420                              <1> 	;
  2421 00002B87 3C08                <1> 	cmp 	al, 8 
  2422 00002B89 7702                <1> 	ja 	short com_i0
  2423                              <1> 	;
  2424                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2425                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2426                              <1> 	; 20/11/2015
  2427                              <1> 	; 17/11/2015
  2428                              <1> 	; 16/11/2015
  2429                              <1> 	; 15/11/2015
  2430                              <1> 	; 24/10/2015
  2431                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2432                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2433                              <1> 	; < serial port 1 interrupt handler >
  2434                              <1> 	;
  2435 00002B8B FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2436                              <1> com_i0:
  2437                              <1> 	;push	eax ; *
  2438                              <1> 	; 07/11/2015
  2439 00002B8D A2[B6620000]        <1> 	mov 	byte [ccomport], al
  2440                              <1> 	; 09/11/2015
  2441                              <1> 	;movzx	ebx, ax ; 8 or 9
  2442                              <1> 	; 08/01/2022
  2443 00002B92 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2444                              <1> 	; 17/11/2015
  2445                              <1>  	; reset request for response status
  2446 00002B94 88A3[AC620000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2447                              <1> 	;
  2448                              <1> 	; 20/11/2015
  2449 00002B9A EC                  <1> 	in	al, dx		; read interrupt id. register
  2450 00002B9B EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2451 00002B9D 2404                <1> 	and	al, 4		; received data available?	
  2452 00002B9F 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2453                              <1> 	;
  2454                              <1> 	; 20/11/2015
  2455 00002BA1 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2456 00002BA4 EC                  <1> 	in	al, dx     	; read character
  2457                              <1> 	;JMP	$+2	   	; I/O DELAY
  2458                              <1> 	; 08/11/2015
  2459                              <1> 	; 07/11/2015
  2460 00002BA5 89DE                <1> 	mov	esi, ebx 
  2461 00002BA7 89DF                <1> 	mov	edi, ebx
  2462 00002BA9 81C6[B0620000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2463 00002BAF 81C7[B2620000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2464 00002BB5 8806                <1> 	mov	[esi], al ; received char (current char)
  2465                              <1> 	; query
  2466 00002BB7 20C0                <1> 	and	al, al
  2467 00002BB9 7527                <1> 	jnz	short com_i2
  2468                              <1>    	; response
  2469                              <1> 	; 17/11/2015
  2470                              <1> 	; set request for response status
  2471 00002BBB FE83[AC620000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2472                              <1> 	;
  2473 00002BC1 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2474 00002BC5 EC                  <1> 	in	al, dx	   	; read line status register 
  2475 00002BC6 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2476 00002BC8 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2477 00002BCA 7445                <1> 	jz	short com_eoi 	; no
  2478 00002BCC B0FF                <1> 	mov 	al, 0FFh   	; response			
  2479 00002BCE 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2480 00002BD2 EE                  <1> 	out	dx, al	   	; send on serial port
  2481                              <1> 	; 17/11/2015
  2482 00002BD3 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2483 00002BD6 7502                <1> 	jne 	short com_i1    ; no
  2484 00002BD8 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2485                              <1> com_i1:
  2486                              <1> 	; 17/11/2015
  2487                              <1> 	; reset request for response status (again)
  2488 00002BDA FE8B[AC620000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2489 00002BE0 EB2F                <1> 	jmp	short com_eoi
  2490                              <1> com_i2:	
  2491                              <1> 	; 08/11/2015
  2492 00002BE2 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2493 00002BE4 7417                <1> 	je	short com_i3	; (check for response signal)
  2494                              <1> 	; 07/11/2015
  2495 00002BE6 3C04                <1> 	cmp	al, 04h	; EOT
  2496 00002BE8 751C                <1> 	jne	short com_i4	
  2497                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2498                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2499                              <1> 	; 08/11/2015
  2500                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2501 00002BEA 861D[76620000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2502 00002BF0 E80BFFFFFF          <1> 	call 	ctrlbrk
  2503 00002BF5 861D[76620000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2504                              <1> 	;mov	al, 04h ; EOT
  2505                              <1> 	; 08/11/2015
  2506 00002BFB EB09                <1> 	jmp	short com_i4	
  2507                              <1> com_i3:
  2508                              <1> 	; 08/11/2015
  2509                              <1> 	; If 0FFh has been received just after a query
  2510                              <1> 	; (schar, ZERO), it is a response signal.
  2511                              <1> 	; 17/11/2015
  2512 00002BFD 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2513 00002C00 7704                <1> 	ja	short com_i4 ; no
  2514                              <1> 	; reset query status (schar)
  2515 00002C02 8807                <1> 	mov	[edi], al ; 0FFh
  2516 00002C04 FEC0                <1> 	inc	al ; 0
  2517                              <1> com_i4:
  2518                              <1> 	; 27/07/2014
  2519                              <1> 	; 09/07/2014
  2520 00002C06 D0E3                <1> 	shl	bl, 1	
  2521 00002C08 81C3[78620000]      <1> 	add	ebx, ttychr
  2522                              <1> 	; 23/07/2014 (always overwrite)
  2523                              <1> 	;;cmp	word [ebx], 0
  2524                              <1> 	;;ja	short com_eoi
  2525                              <1> 	;
  2526 00002C0E 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2527                              <1> 			    ; scan code = 0
  2528                              <1> com_eoi:
  2529                              <1> 	;mov	al, 20h
  2530                              <1> 	;out	20h, al	   ; end of interrupt
  2531                              <1> 	;
  2532                              <1> 	; 07/11/2015
  2533                              <1>       	;pop	eax ; *
  2534 00002C11 A0[B6620000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2535                              <1> 	; al = tty number (8 or 9)
  2536 00002C16 E8F31A0000          <1>         call	wakeup
  2537                              <1> com_iret:
  2538                              <1> 	; 23/10/2015
  2539 00002C1B 5A                  <1> 	pop	edx ; **
  2540 00002C1C 59                  <1> 	pop	ecx ; ***
  2541                              <1> 	; 18/11/2015
  2542                              <1> 	;pop	eax ; ****
  2543                              <1> 	;mov	cr3, eax
  2544                              <1> 	;jmp	iiret
  2545 00002C1D E97ADDFFFF          <1> 	jmp	iiretp
  2546                              <1> 
  2547                              <1> ;hfgchr:
  2548                              <1> ;	db '0123456789ABCDEF?*'
  2549                              <1> ;	db 0
  2550                              <1> 
  2551                              <1> ;iiretp: ; 01/09/2015
  2552                              <1> ;	; 28/08/2015
  2553                              <1> ;	pop	eax ; (*) page directory
  2554                              <1> ;	mov	cr3, eax
  2555                              <1> ;iiret:
  2556                              <1> ;	; 22/08/2014
  2557                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2558                              <1> ;	out	20h, al	; 8259 PORT
  2559                              <1> ;	;
  2560                              <1> ;	pop	es
  2561                              <1> ;	pop	ds
  2562                              <1> ;	pop	edi
  2563                              <1> ;	pop	esi
  2564                              <1> ;	pop	ebx ; 29/08/2014
  2565                              <1> ;	pop 	eax
  2566                              <1> ;	iretd
  2567                              <1> 
  2568                              <1> sp_init:
  2569                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2570                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2571                              <1> 	; 07/11/2015
  2572                              <1> 	; 29/10/2015
  2573                              <1> 	; 26/10/2015
  2574                              <1> 	; 23/10/2015
  2575                              <1> 	; 29/06/2015
  2576                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2577                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2578                              <1> 	; Initialization of Serial Port Communication Parameters
  2579                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2580                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2581                              <1> 	;
  2582                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2583                              <1> 	;
  2584                              <1> 	; INPUT:  (29/06/2015)
  2585                              <1> 	;	AL = 0 for COM1
  2586                              <1> 	;	     1 for COM2
  2587                              <1> 	;	AH = Communication parameters	
  2588                              <1> 	;
  2589                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2590                              <1> 	;	Bit	4	3	2	1	0
  2591                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2592                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2593                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2594                              <1> 	;		11 = even
  2595                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2596                              <1> 	;		Retro UNIX 386 v1 feature only !
  2597                              <1> 	;	Bit	7    6    5  | Baud rate
  2598                              <1> 	;		------------------------
  2599                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2600                              <1> 	;		0    0    1  | 9600 (12)
  2601                              <1> 	;		0    1    0  | 19200 (6) 
  2602                              <1> 	;		0    1	  1  | 38400 (3) 
  2603                              <1> 	;		1    0	  0  | 14400 (8)
  2604                              <1> 	;		1    0	  1  | 28800 (4)
  2605                              <1> 	;		1    1    0  | 57600 (2)
  2606                              <1> 	;		1    1    1  | 115200 (1) 	
  2607                              <1> 	
  2608                              <1> 	; References:	
  2609                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2610                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2611                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2612                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2613                              <1> 	;
  2614                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2615                              <1> 	;
  2616 00002C22 BB[B2620000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2617 00002C27 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2618                              <1> 	; 29/10/2015
  2619 00002C2B 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2620 00002C2F E84F000000          <1> 	call	sp_i3	; call A4	
  2621 00002C34 A880                <1> 	test	al, 80h
  2622 00002C36 740E                <1> 	jz	short sp_i0 ; OK..
  2623                              <1> 		; Error !
  2624                              <1> 	;mov	dx, 3F8h
  2625 00002C38 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2626                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2627                              <1> 	; 08/01/2022
  2628 00002C3B B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2629 00002C3D E841000000          <1> 	call	sp_i3	; call A4	
  2630 00002C42 A880                <1> 	test	al, 80h
  2631 00002C44 7508                <1> 	jnz	short sp_i1
  2632                              <1> sp_i0:
  2633                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2634                              <1>         ; (INT 14h initialization code disables interrupts.)
  2635                              <1> 	;
  2636 00002C46 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2637 00002C49 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2638                              <1> sp_i1:
  2639 00002C4E 43                  <1> 	inc	ebx
  2640 00002C4F 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2641                              <1> 	; 29/10/2015
  2642                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2643                              <1> 	; 08/01/2022
  2644 00002C53 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2645 00002C55 E829000000          <1> 	call	sp_i3	; call A4	
  2646 00002C5A A880                <1> 	test	al, 80h
  2647 00002C5C 740E                <1> 	jz	short sp_i2 ; OK..
  2648                              <1> 		; Error !
  2649                              <1> 	;mov	dx, 2F8h
  2650 00002C5E 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2651                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2652                              <1> 	; 08/01/2022
  2653 00002C61 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2654 00002C63 E81B000000          <1> 	call	sp_i3	; call A4	
  2655 00002C68 A880                <1> 	test	al, 80h
  2656 00002C6A 7516                <1> 	jnz	short sp_i7
  2657                              <1> sp_i2:
  2658 00002C6C C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2659                              <1> sp_i6:
  2660                              <1> 	;; COM2 - enabling IRQ 3
  2661                              <1> 	; 08/01/2022
  2662 00002C6F B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2663                              <1> 	; 07/11/2015
  2664                              <1> 	; 26/10/2015
  2665                              <1> 	;pushf
  2666                              <1> 	;cli
  2667                              <1> 	;;
  2668                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2669                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2670                              <1> 	;in	al, dx 	   		; read register
  2671                              <1> 	;JMP	$+2	   		; I/O DELAY
  2672                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2673                              <1> 	;out	dx, al     		; write back to register
  2674                              <1> 	;JMP	$+2	   		; I/O DELAY
  2675                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2676                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2677                              <1> 	;in	al, dx     		; read register
  2678                              <1> 	;JMP	$+2	   		; I/O DELAY
  2679                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2680                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2681                              <1> 	;out	dx, al 	   		; write back to register
  2682                              <1> 	;JMP	$+2        		; I/O DELAY
  2683                              <1> 	;in	al, 21h    		; read interrupt mask register
  2684                              <1> 	;JMP	$+2	   		; I/O DELAY
  2685                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2686                              <1> 	;out	21h, al    		; write back to register
  2687                              <1> 	;
  2688                              <1> 	; 08/01/2022
  2689 00002C71 9C                  <1> 	pushf
  2690 00002C72 E8AA000000          <1> 	call	sp_i8
  2691                              <1> 	; 23/10/2015
  2692 00002C77 B8[562B0000]        <1> 	mov 	eax, com2_int
  2693 00002C7C A3[0A310000]        <1> 	mov	[com2_irq3], eax
  2694                              <1> 	; 26/10/2015
  2695 00002C81 9D                  <1> 	popf	
  2696                              <1> sp_i7:
  2697 00002C82 C3                  <1> 	retn
  2698                              <1> 
  2699                              <1> sp_i3:
  2700                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2701                              <1> 	; 28/10/2015
  2702 00002C83 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2703 00002C85 B000                <1> 	mov	al, 0
  2704 00002C87 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2705 00002C88 EB00                <1> 	JMP	$+2			; I/O DELAY
  2706 00002C8A 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2707 00002C8D B080                <1> 	mov	al, 80h			
  2708 00002C8F EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2709                              <1> 	;-----	SET BAUD RATE DIVISOR
  2710                              <1> 	; 26/10/2015
  2711 00002C90 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2712                              <1> 					; of the divisor value
  2713 00002C93 88C8                <1> 	mov	al, cl	; 1
  2714 00002C95 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2715                              <1> 					; 2 = 57600 baud
  2716                              <1> 					; 3 = 38400 baud
  2717                              <1> 					; 6 = 19200 baud
  2718                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2719 00002C96 EB00                <1> 	JMP	$+2			; I/O DELAY
  2720 00002C98 28C0                <1> 	sub	al, al
  2721 00002C9A FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2722                              <1> 					; of the divisor value
  2723 00002C9C EE                  <1> 	out	dx, al ; 0
  2724 00002C9D EB00                <1> 	JMP	$+2			; I/O DELAY
  2725                              <1> 	;	
  2726 00002C9F 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2727                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2728 00002CA1 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2729 00002CA4 EE                  <1> 	out	dx, al			
  2730 00002CA5 EB00                <1> 	JMP	$+2			; I/O DELAY
  2731                              <1> 	; 29/10/2015
  2732 00002CA7 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2733 00002CA9 30C0                <1> 	xor	al, al			; 0
  2734 00002CAB EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2735 00002CAC EB00                <1> 	JMP	$+2	
  2736                              <1> sp_i4:
  2737                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2738                              <1> 	; 29/06/2015 (line status after modem status)
  2739 00002CAE 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2740                              <1> sp_i4s:
  2741 00002CB1 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2742 00002CB2 EB00                <1> 	JMP	$+2			; I/O DELAY
  2743 00002CB4 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2744 00002CB6 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2745                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2746 00002CB8 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2747                              <1> 	; AL = Line status, AH = Modem status
  2748 00002CB9 C3                  <1> 	retn
  2749                              <1> 
  2750                              <1> sp_status:
  2751                              <1> 	; 29/06/2015
  2752                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2753                              <1> 	; Get serial port status
  2754 00002CBA 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2755 00002CBE 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2756                              <1> 					; dx = 2FEh for COM2
  2757 00002CC0 EBEF                <1> 	jmp	short sp_i4s
  2758                              <1> 
  2759                              <1> sp_setp: ; Set serial port communication parameters
  2760                              <1> 	; 04/02/2022 
  2761                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2762                              <1> 	; 08/01/2022
  2763                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2764                              <1> 	; 07/11/2015
  2765                              <1> 	; 29/10/2015
  2766                              <1> 	; 29/06/2015
  2767                              <1> 	; Retro UNIX 386 v1 feature only !	
  2768                              <1> 	;
  2769                              <1> 	; INPUT:
  2770                              <1> 	;	AL = 0 for COM1
  2771                              <1> 	;	     1 for COM2
  2772                              <1> 	;	AH = Communication parameters (*)
  2773                              <1> 	; OUTPUT:
  2774                              <1> 	;	CL = Line status
  2775                              <1> 	;	CH = Modem status
  2776                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2777                              <1> 	;		 'invalid parameter !' 
  2778                              <1> 	;		 	 or
  2779                              <1> 	;		 'device not ready !' error
  2780                              <1> 	;	
  2781                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2782                              <1> 	;	Bit	4	3	2	1	0
  2783                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2784                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2785                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2786                              <1> 	;		11 = even
  2787                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2788                              <1> 	;		Retro UNIX 386 v1 feature only !
  2789                              <1> 	;	Bit	7    6    5  | Baud rate
  2790                              <1> 	;		------------------------
  2791                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2792                              <1> 	;		0    0    1  | 9600 (12)
  2793                              <1> 	;		0    1    0  | 19200 (6) 
  2794                              <1> 	;		0    1	  1  | 38400 (3) 
  2795                              <1> 	;		1    0	  0  | 14400 (8)
  2796                              <1> 	;		1    0	  1  | 28800 (4)
  2797                              <1> 	;		1    1    0  | 57600 (2)
  2798                              <1> 	;		1    1    1  | 115200 (1) 
  2799                              <1> 	;
  2800                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2801                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2802                              <1> 	;
  2803                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2804                              <1> 	;
  2805 00002CC2 66BAF803            <1> 	mov	dx, 3F8h
  2806 00002CC6 BB[B2620000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2807 00002CCB 3C01                <1> 	cmp	al, 1
  2808 00002CCD 7770                <1> 	ja 	short sp_invp_err
  2809 00002CCF 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2810 00002CD1 FECE                <1> 	dec	dh ; 2F8h
  2811 00002CD3 43                  <1> 	inc	ebx ; COM2 control byte offset
  2812                              <1> sp_setp1:
  2813                              <1> 	; 29/10/2015
  2814 00002CD4 8823                <1> 	mov	[ebx], ah
  2815 00002CD6 0FB6CC              <1> 	movzx 	ecx, ah
  2816 00002CD9 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2817 00002CDC 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2818 00002CDF 8A81[4E2D0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2819 00002CE5 6689C1              <1> 	mov	cx, ax
  2820 00002CE8 E896FFFFFF          <1> 	call	sp_i3
  2821 00002CED 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2822 00002CF0 A880                <1> 	test	al, 80h
  2823 00002CF2 740F                <1> 	jz	short sp_setp2
  2824 00002CF4 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2825                              <1> stp_dnr_err:
  2826 00002CF7 C705[5F660000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2826 00002CFF 0000                <1>
  2827                              <1> 	; CL = Line status, CH = Modem status
  2828 00002D01 F9                  <1> 	stc
  2829 00002D02 C3                  <1> 	retn
  2830                              <1> sp_setp2:
  2831 00002D03 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2832                              <1>         ;jna	sp_i6
  2833                              <1> 		      ; COM1 (3F?h)
  2834                              <1> 	; 24/12/2021
  2835 00002D06 7705                <1> 	ja	short sp_i5
  2836 00002D08 E962FFFFFF          <1> 	jmp	sp_i6
  2837                              <1> sp_i5: 
  2838                              <1> 	; 08/01/2022
  2839 00002D0D B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2840                              <1> 	; 07/11/2015
  2841                              <1> 	; 26/10/2015
  2842                              <1> 	; 29/06/2015
  2843                              <1> 	;
  2844                              <1> 	;; COM1 - enabling IRQ 4
  2845                              <1> 	;pushf
  2846                              <1> 	;cli
  2847                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2848                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2849                              <1> 	;in	al, dx 	   		; read register
  2850                              <1> 	;JMP	$+2			; I/O DELAY
  2851                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2852                              <1> 	;out	dx, al     		; write back to register
  2853                              <1> 	;JMP	$+2			; I/O DELAY
  2854                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2855                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2856                              <1> 	;in	al, dx     		; read register
  2857                              <1> 	;JMP	$+2			; I/O DELAY
  2858                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2859                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2860                              <1> 	;out	dx, al 	   		; write back to register
  2861                              <1> 	;JMP	$+2        		; I/O DELAY
  2862                              <1> 	;in	al, 21h    		; read interrupt mask register
  2863                              <1> 	;JMP	$+2			; I/O DELAY
  2864                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2865                              <1> 	;out	21h, al    		; write back to register
  2866                              <1> 	;
  2867                              <1> 	; 08/01/2022
  2868 00002D0F 9C                  <1> 	pushf
  2869 00002D10 E80C000000          <1> 	call	sp_i8
  2870                              <1> 	; 23/10/2015
  2871 00002D15 B8[5F2B0000]        <1> 	mov 	eax, com1_int
  2872 00002D1A A3[06310000]        <1> 	mov	[com1_irq4], eax
  2873                              <1> 	; 26/10/2015
  2874 00002D1F 9D                  <1> 	popf
  2875 00002D20 C3                  <1> 	retn
  2876                              <1> 
  2877                              <1> sp_i8:
  2878                              <1> 	; 08/01/2022
  2879                              <1> 	;pushf
  2880 00002D21 FA                  <1> 	cli
  2881                              <1> 	;
  2882                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2883 00002D22 B2FC                <1> 	mov	dl, 0FCh
  2884 00002D24 EC                  <1> 	in	al, dx 	   		; read register
  2885 00002D25 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2886 00002D27 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2887 00002D29 EE                  <1> 	out	dx, al     		; write back to register
  2888 00002D2A EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2889                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2890 00002D2C B2F9                <1> 	mov	dl, 0F9h
  2891 00002D2E EC                  <1> 	in	al, dx     		; read register
  2892 00002D2F EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2893                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2894 00002D31 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2895 00002D33 EE                  <1> 	out	dx, al 	   		; write back to register
  2896 00002D34 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2897 00002D36 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2898 00002D38 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2899                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2900 00002D3A 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2901 00002D3C E621                <1> 	out	21h, al    		; write back to register
  2902                              <1> 	;
  2903                              <1> 	;popf	
  2904 00002D3E C3                  <1> 	retn
  2905                              <1> 
  2906                              <1> sp_invp_err:
  2907 00002D3F C705[5F660000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2907 00002D47 0000                <1>
  2908 00002D49 31C9                <1> 	xor	ecx, ecx
  2909 00002D4B 49                  <1> 	dec	ecx ; 0FFFFh
  2910 00002D4C F9                  <1> 	stc
  2911 00002D4D C3                  <1> 	retn
  2912                              <1> 
  2913                              <1> ; 29/10/2015
  2914                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2915 00002D4E 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2916                              <1> 
  2917                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2918                              <1> epoch:
  2919                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2920                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2921                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2922                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2923                              <1> 	; 'epoch' procedure prototype: 
  2924                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2925                              <1> 	; 14/11/2012
  2926                              <1> 	; unixboot.asm (boot file configuration)
  2927                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2928                              <1> 	; 21/7/2012
  2929                              <1> 	; 15/7/2012
  2930                              <1> 	; 14/7/2012		
  2931                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2932                              <1> 	; compute current date and time as UNIX Epoch/Time
  2933                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2934                              <1> 	;
  2935                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2936                              <1> 	;
  2937 00002D55 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2938 00002D5A 86E9                <1>         xchg 	ch,cl
  2939 00002D5C 66890D[B65F0000]    <1>         mov 	[hour], cx
  2940 00002D63 86F2                <1>         xchg 	dh,dl
  2941 00002D65 668915[B85F0000]    <1>         mov 	[second], dx
  2942                              <1> 	;
  2943 00002D6C E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2944 00002D71 86E9                <1>         xchg 	ch,cl
  2945 00002D73 66890D[B25F0000]    <1>         mov 	[year], cx
  2946 00002D7A 86F2                <1>         xchg 	dh,dl
  2947 00002D7C 668915[B45F0000]    <1>         mov 	[month], dx
  2948                              <1> 	;
  2949 00002D83 66B93030            <1> 	mov 	cx, 3030h
  2950                              <1> 	;
  2951 00002D87 A0[B65F0000]        <1> 	mov 	al, [hour] ; Hour
  2952                              <1>         	; AL <= BCD number)
  2953 00002D8C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2954                              <1> 					; AH = AL / 10h
  2955                              <1> 					; AL = AL MOD 10h
  2956 00002D8E D50A                <1>         aad 	; AX= AH*10+AL
  2957 00002D90 A2[B65F0000]        <1> 	mov 	[hour], al
  2958 00002D95 A0[B75F0000]        <1> 	mov 	al, [hour+1] ; Minute
  2959                              <1>         	; AL <= BCD number)
  2960 00002D9A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2961                              <1> 					; AH = AL / 10h
  2962                              <1> 					; AL = AL MOD 10h
  2963 00002D9C D50A                <1>         aad 	; AX= AH*10+AL
  2964 00002D9E A2[B75F0000]        <1> 	mov 	[minute], al
  2965 00002DA3 A0[B85F0000]        <1> 	mov 	al, [second] ; Second
  2966                              <1>         	; AL <= BCD number)
  2967 00002DA8 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2968                              <1> 					; AH = AL / 10h
  2969                              <1> 					; AL = AL MOD 10h
  2970 00002DAA D50A                <1>         aad 	; AX= AH*10+AL
  2971 00002DAC A2[B85F0000]        <1> 	mov 	[second], al
  2972 00002DB1 66A1[B25F0000]      <1> 	mov 	ax, [year] ; Year (century)
  2973                              <1>  	;push 	ax
  2974                              <1> 	; 08/01/2022
  2975 00002DB7 50                  <1> 	push	eax
  2976                              <1> 	   	; AL <= BCD number)
  2977 00002DB8 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2978                              <1> 					; AH = AL / 10h
  2979                              <1> 					; AL = AL MOD 10h
  2980 00002DBA D50A                <1>         aad 	; AX= AH*10+AL
  2981 00002DBC B464                <1> 	mov 	ah, 100
  2982 00002DBE F6E4                <1> 	mul 	ah
  2983 00002DC0 66A3[B25F0000]      <1> 	mov 	[year], ax
  2984                              <1> 	;pop	ax
  2985                              <1> 	; 08/01/2022
  2986 00002DC6 58                  <1> 	pop	eax
  2987 00002DC7 88E0                <1> 	mov	al, ah
  2988                              <1>         	; AL <= BCD number)
  2989 00002DC9 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2990                              <1> 					; AH = AL / 10h
  2991                              <1> 					; AL = AL MOD 10h
  2992 00002DCB D50A                <1>         aad 	; AX= AH*10+AL
  2993 00002DCD 660105[B25F0000]    <1> 	add 	[year], ax
  2994 00002DD4 A0[B45F0000]        <1> 	mov 	al, [month] ; Month
  2995                              <1>            	; AL <= BCD number)
  2996 00002DD9 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2997                              <1> 					; AH = AL / 10h
  2998                              <1> 					; AL = AL MOD 10h
  2999 00002DDB D50A                <1>         aad 	; AX= AH*10+AL
  3000 00002DDD A2[B45F0000]        <1> 	mov 	[month], al	
  3001 00002DE2 A0[B55F0000]        <1>         mov     al, [month+1]      	; Day
  3002                              <1>            	; AL <= BCD number)
  3003 00002DE7 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3004                              <1> 					; AH = AL / 10h
  3005                              <1> 					; AL = AL MOD 10h
  3006 00002DE9 D50A                <1>         aad 	; AX= AH*10+AL
  3007 00002DEB A2[B55F0000]        <1>         mov     [day], al
  3008                              <1> 	
  3009                              <1> convert_to_epoch:
  3010                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3011                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  3012                              <1> 	;
  3013                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3014                              <1> 	;
  3015                              <1> 	; Derived from DALLAS Semiconductor
  3016                              <1> 	; Application Note 31 (DS1602/DS1603)
  3017                              <1> 	; 6 May 1998
  3018 00002DF0 29C0                <1> 	sub 	eax, eax
  3019 00002DF2 66A1[B25F0000]      <1> 	mov 	ax, [year]
  3020 00002DF8 662DB207            <1> 	sub 	ax, 1970
  3021 00002DFC BA6D010000          <1> 	mov 	edx, 365
  3022 00002E01 F7E2                <1> 	mul 	edx
  3023 00002E03 31DB                <1> 	xor 	ebx, ebx
  3024 00002E05 8A1D[B45F0000]      <1> 	mov 	bl, [month]
  3025 00002E0B FECB                <1> 	dec 	bl
  3026 00002E0D D0E3                <1> 	shl 	bl, 1
  3027                              <1> 	;sub	edx, edx
  3028 00002E0F 668B93[BA5F0000]    <1> 	mov 	dx, [EBX+DMonth]
  3029 00002E16 8A1D[B55F0000]      <1>         mov     bl, [day]
  3030 00002E1C FECB                <1> 	dec 	bl
  3031 00002E1E 01D0                <1> 	add 	eax, edx
  3032 00002E20 01D8                <1> 	add 	eax, ebx
  3033                              <1> 			; EAX = days since 1/1/1970
  3034 00002E22 668B15[B25F0000]    <1> 	mov 	dx, [year]
  3035 00002E29 6681EAB107          <1> 	sub 	dx, 1969
  3036 00002E2E 66D1EA              <1> 	shr 	dx, 1
  3037 00002E31 66D1EA              <1> 	shr 	dx, 1		
  3038                              <1> 		; (year-1969)/4
  3039 00002E34 01D0                <1> 	add 	eax, edx
  3040                              <1> 			; + leap days since 1/1/1970
  3041 00002E36 803D[B45F0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3042 00002E3D 7610                <1> 	jna 	short cte1
  3043 00002E3F 668B15[B25F0000]    <1> 	mov 	dx, [year]
  3044 00002E46 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3045 00002E4A 7503                <1> 	jnz 	short cte1		
  3046                              <1> 			; and if leap year
  3047 00002E4C 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3048                              <1> cte1: 			; compute seconds since 1/1/1970
  3049 00002E4F BA18000000          <1> 	mov 	edx, 24
  3050 00002E54 F7E2                <1> 	mul	edx
  3051 00002E56 8A15[B65F0000]      <1> 	mov 	dl, [hour]
  3052 00002E5C 01D0                <1> 	add 	eax, edx
  3053                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3054                              <1> 	;mov	ebx, 60
  3055 00002E5E B33C                <1> 	mov	bl, 60
  3056 00002E60 F7E3                <1> 	mul	ebx
  3057 00002E62 8A15[B75F0000]      <1> 	mov 	dl, [minute]
  3058 00002E68 01D0                <1> 	add 	eax, edx
  3059                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3060                              <1> 	;mov 	ebx, 60
  3061 00002E6A F7E3                <1> 	mul	ebx
  3062 00002E6C 8A15[B85F0000]      <1> 	mov 	dl, [second]
  3063 00002E72 01D0                <1> 	add 	eax, edx
  3064                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3065 00002E74 C3                  <1> 	retn
  3066                              <1> 
  3067                              <1> get_rtc_time:
  3068                              <1> 	; 15/03/2015
  3069                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3070                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3071                              <1> 	; INT 1Ah						:
  3072                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3073                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3074                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3075                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3076                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3077                              <1> 	;								
  3078                              <1> RTC_20: 			; GET RTC TIME
  3079 00002E75 FA                  <1> 	cli
  3080 00002E76 E8BFDCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3081 00002E7B 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3082                              <1> 
  3083 00002E7D B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3084 00002E7F E89EDCFFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3085 00002E84 88C6                <1> 	MOV	DH,AL		; SAVE
  3086 00002E86 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3087 00002E88 E895DCFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3088 00002E8D 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3089 00002E8F 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3090 00002E91 B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3091 00002E93 E88ADCFFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3092 00002E98 88C1                <1> 	MOV	CL,AL		; SAVE
  3093 00002E9A B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3094 00002E9C E881DCFFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3095 00002EA1 88C5                <1> 	MOV	CH,AL		; SAVE
  3096 00002EA3 F8                  <1> 	CLC			; SET CY= 0
  3097                              <1> RTC_29:
  3098 00002EA4 FB                  <1> 	sti
  3099 00002EA5 C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3100                              <1> 
  3101                              <1> get_rtc_date:
  3102                              <1> 	; 15/03/2015
  3103                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3104                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3105                              <1> 	; INT 1Ah						       :
  3106                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3107                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3108                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3109                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3110                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3111                              <1> 	;
  3112                              <1> RTC_40: 			; GET RTC DATE
  3113 00002EA6 FA                  <1> 	cli
  3114 00002EA7 E88EDCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3115 00002EAC 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3116                              <1> 
  3117 00002EAE B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3118 00002EB0 E86DDCFFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3119 00002EB5 88C2                <1> 	MOV	DL,AL		; SAVE
  3120 00002EB7 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3121 00002EB9 E864DCFFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3122 00002EBE 88C6                <1> 	MOV	DH,AL		; SAVE
  3123 00002EC0 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3124 00002EC2 E85BDCFFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3125 00002EC7 88C1                <1> 	MOV	CL,AL		; SAVE
  3126 00002EC9 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3127 00002ECB E852DCFFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3128 00002ED0 88C5                <1> 	MOV	CH,AL		; SAVE
  3129 00002ED2 F8                  <1> 	CLC			; SET CY=0
  3130                              <1> RTC_49:
  3131 00002ED3 FB                  <1> 	sti
  3132 00002ED4 C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3133                              <1> 
  3134                              <1> set_date_time:
  3135                              <1> convert_from_epoch:
  3136                              <1> 	; 02/06/2022
  3137                              <1> 	; 01/06/2022 (BugFix)
  3138                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3139                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3140                              <1> 	; 'convert_from_epoch' procedure prototype:
  3141                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3142                              <1> 	;
  3143                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))
  3144                              <1> 	;
  3145                              <1> 	; Derived from DALLAS Semiconductor
  3146                              <1> 	; Application Note 31 (DS1602/DS1603)
  3147                              <1> 	; 6 May 1998
  3148                              <1> 	;
  3149                              <1> 	; INPUT:
  3150                              <1> 	; EAX = Unix (Epoch) Time
  3151                              <1> 	;
  3152 00002ED5 31D2                <1> 	xor 	edx, edx
  3153                              <1> 	; 02/06/2022
  3154 00002ED7 31C9                <1> 	xor	ecx, ecx
  3155 00002ED9 31DB                <1> 	xor	ebx, ebx
  3156                              <1> 	;mov 	ecx, 60
  3157 00002EDB B13C                <1> 	mov	cl, 60
  3158 00002EDD F7F1                <1> 	div	ecx
  3159                              <1> 	;mov 	[imin], eax  ; whole minutes
  3160                              <1> 			     ; since 1/1/1970
  3161                              <1> 	;mov 	[second], dx ; leftover seconds
  3162 00002EDF 8815[B85F0000]      <1> 	mov	[second], dl ; 02/06/2022
  3163 00002EE5 29D2                <1> 	sub 	edx, edx
  3164 00002EE7 F7F1                <1> 	div	ecx
  3165                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3166                              <1> 	;		     ; since 1/1/1970
  3167                              <1> 	;mov 	[minute], dx ; leftover minutes
  3168 00002EE9 8815[B75F0000]      <1> 	mov	[minute], dl ; 02/06/2022
  3169 00002EEF 31D2                <1> 	xor	edx, edx
  3170                              <1> 	;mov 	cx, 24
  3171 00002EF1 B118                <1> 	mov 	cl, 24
  3172 00002EF3 F7F1                <1> 	div	ecx
  3173                              <1> 	;mov 	[iday], ax   ; whole days
  3174                              <1> 			     ; since 1/1/1970
  3175                              <1> 	;mov 	[hour], dx   ; leftover hours
  3176 00002EF5 8815[B65F0000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3177                              <1> 
  3178 00002EFB 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3179                              <1> 			     ; 1/1/1968 	
  3180                              <1> 	;mov 	[iday], ax
  3181 00002F00 50                  <1> 	push 	eax
  3182 00002F01 29D2                <1> 	sub	edx, edx
  3183 00002F03 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3184 00002F08 F7F1                <1> 	div	ecx
  3185 00002F0A 59                  <1> 	pop 	ecx
  3186                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3187                              <1> 	;push	dx
  3188                              <1> 	; 01/06/2022
  3189 00002F0B 52                  <1> 	push 	edx
  3190                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3191 00002F0C 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3192 00002F10 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3193 00002F11 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3194                              <1> 	;mov 	[lday], ax   ; since 1968
  3195                              <1> 	;mov 	cx, [iday]
  3196 00002F14 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday
  3197 00002F15 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3198 00002F17 B96D010000          <1> 	mov 	ecx, 365
  3199 00002F1C 31D2                <1> 	xor	edx, edx
  3200                              <1> 	; EAX = iday-lday, EDX = 0
  3201 00002F1E F7F1                <1> 	div	ecx
  3202                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3203                              <1> 	;jday = iday - (iyrs*365) - lday
  3204                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3205                              <1> 	;add	eax, 1968
  3206 00002F20 6605B007            <1> 	add 	ax, 1968     ; compute year
  3207 00002F24 66A3[B25F0000]      <1> 	mov 	[year], ax
  3208                              <1> 	;mov 	cx, dx
  3209                              <1> 	; 02/06/2022
  3210 00002F2A 89D1                <1> 	mov	ecx, edx
  3211                              <1> 	;mov 	dx, [qday]
  3212                              <1> 	;pop	dx
  3213                              <1> 	; 01/06/2022
  3214 00002F2C 5A                  <1> 	pop 	edx
  3215 00002F2D 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3216 00002F32 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3217 00002F34 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3218 00002F38 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3219 00002F39 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3220                              <1> cfe1:			
  3221                              <1> 	;mov 	[jday], cx
  3222                              <1> 	;mov 	bx, 12       ; estimate month
  3223                              <1> 	;sub	ebx, ebx
  3224                              <1> 	; 02/06/2022
  3225 00002F3D B30C                <1> 	mov	bl, 12
  3226 00002F3F 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3227 00002F43 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3228                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3229                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3230                              <1> 	; 02/06/2022
  3231 00002F47 39D1                <1> 	cmp	ecx, edx 	 		
  3232 00002F49 7319                <1> 	jnb 	short cfe3
  3233                              <1> 	;dec 	bx           ; month = month - 1
  3234 00002F4B FECB                <1> 	dec	bl			
  3235                              <1> 	;shl 	bx, 1
  3236 00002F4D D0E3                <1> 	shl	bl, 1
  3237 00002F4F 668B93[BA5F0000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3238                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3239                              <1> 	; 02/06/2022
  3240 00002F56 D0EB                <1> 	shr	bl, 1
  3241 00002F58 80FB01              <1> 	cmp	bl, 1
  3242                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0
  3243 00002F5B 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3244 00002F5D 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3245 00002F5F 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3246                              <1> 	;inc 	dx           ; mday = mday + 1
  3247 00002F61 42                  <1> 	inc	edx
  3248 00002F62 EBE3                <1> 	jmp 	short cfe2
  3249                              <1> cfe3:
  3250                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3251                              <1> 	; 02/06/2022
  3252 00002F64 FEC3                <1> 	inc	bl
  3253                              <1> 	;mov 	[month], bx
  3254 00002F66 881D[B45F0000]      <1> 	mov	[month], bl
  3255                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1
  3256 00002F6C 29D1                <1> 	sub	ecx, edx
  3257                              <1> 	;inc 	cx
  3258 00002F6E FEC1                <1> 	inc	cl
  3259                              <1> 	;mov 	[day], cx
  3260 00002F70 880D[B55F0000]      <1> 	mov	[day], cl    ; 02/06/2022
  3261                              <1> 	
  3262                              <1> 	; eax, ebx, ecx, edx is changed at return
  3263                              <1> 	; output ->
  3264                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3265                              <1> 	
  3266                              <1> 	; 01/06/2022 (BugFix)
  3267                              <1> _set_date:
  3268 00002F76 66A1[B25F0000]      <1> 	mov	ax, [year]
  3269 00002F7C B520                <1> 	mov	ch, 20h ; century (bcd)
  3270 00002F7E 662DD007            <1> 	sub	ax, 2000
  3271 00002F82 7306                <1> 	jnc	short set_date
  3272 00002F84 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3273 00002F86 6683C064            <1> 	add	ax, 100	
  3274                              <1> 	; 01/06/2022
  3275                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3276                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3277                              <1> set_date:
  3278                              <1>         ;mov	al, [year+1]
  3279                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3280                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3281                              <1> 	;		     ; AL = AH * 10h + AL
  3282                              <1> 	;mov 	ch, al ; century (BCD)
  3283                              <1> 	;mov 	al, [year]
  3284                              <1> 	; al = year (0-99) ; 01/06/2022
  3285 00002F8A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3286 00002F8C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3287                              <1> 			     ; AL = AH * 10h + AL
  3288 00002F8E 88C1                <1> 	mov 	cl, al ; year (BCD)
  3289 00002F90 A0[B45F0000]        <1>         mov 	al, [month]
  3290 00002F95 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3291 00002F97 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3292                              <1> 			     ; AL = AH * 10h + AL
  3293 00002F99 88C6                <1> 	mov 	dh, al ; month (BCD)
  3294 00002F9B A0[B55F0000]        <1> 	mov 	al, [day]
  3295 00002FA0 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3296 00002FA2 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3297                              <1> 			     ; AL = AH * 10h + AL
  3298                              <1> 	; 01/06/2022 (BugFix)
  3299 00002FA4 88C2                <1> 	mov 	dl, al ; day (BCD)
  3300                              <1> 
  3301                              <1> 	; Set real-time clock date
  3302 00002FA6 E879000000          <1> 	call	set_rtc_date
  3303                              <1> set_time:
  3304                              <1>         ; Read real-time clock time 
  3305                              <1> 	; (get day light saving time bit status)
  3306 00002FAB FA                  <1>  	cli
  3307 00002FAC E889DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3308                              <1> 	; cf = 1 -> al = 0
  3309 00002FB1 7207                <1>         jc      short stime1
  3310 00002FB3 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3311 00002FB5 E868DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3312                              <1> stime1:
  3313 00002FBA FB                  <1> 	sti
  3314 00002FBB 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3315 00002FBD 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3316                              <1> 	; DL = 1 or 0 (day light saving time)
  3317                              <1> 	;	
  3318 00002FBF A0[B65F0000]        <1> 	mov 	al, [hour]
  3319 00002FC4 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3320 00002FC6 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3321                              <1> 			     ; AL = AH * 10h + AL
  3322 00002FC8 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3323 00002FCA A0[B75F0000]        <1>         mov     al, [minute]
  3324 00002FCF D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3325 00002FD1 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3326                              <1> 			     ; AL = AH * 10h + AL
  3327 00002FD3 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3328 00002FD5 A0[B85F0000]        <1>         mov     al, [second]
  3329 00002FDA D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3330 00002FDC D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3331                              <1> 			     ; AL = AH * 10h + AL
  3332 00002FDE 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3333                              <1> 
  3334                              <1> 	; Set real-time clock time
  3335                              <1>  	; call	set_rtc_time
  3336                              <1> set_rtc_time:
  3337                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3338                              <1> 	; 15/03/2015							  :
  3339                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3340                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3341                              <1> 	; INT 1Ah							  :
  3342                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3343                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3344                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3345                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3346                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3347                              <1> 	;								  :
  3348                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3349                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3350                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3351                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3352                              <1> 	;								  :
  3353                              <1> RTC_30: 			; SET RTC TIME
  3354 00002FE0 FA                  <1> 	cli
  3355 00002FE1 E854DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3356 00002FE6 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3357 00002FE8 E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3358                              <1> RTC_35:
  3359 00002FED 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3360 00002FEF B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3361 00002FF1 E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3362 00002FF6 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3363 00002FF8 B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3364 00002FFA E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3365 00002FFF 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3366 00003001 B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3367 00003003 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3368                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3369 00003008 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3370 0000300C E811DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3371 00003011 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3372 00003013 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3373 00003015 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3374 00003018 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3375 0000301A 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3376 0000301C E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3377 00003021 F8                  <1> 	CLC			; SET CY= 0
  3378 00003022 FB                  <1> 	sti
  3379 00003023 C3                  <1> 	RETn			; RETURN WITH CY= 0
  3380                              <1> 
  3381                              <1> set_rtc_date:
  3382                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)	   :
  3383                              <1> 	; 15/03/2015						   :
  3384                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	   :
  3385                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	   :
  3386                              <1> 	; INT 1Ah						   :
  3387                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3388                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3389                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3390                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3391                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3392                              <1> 	;							   :
  3393                              <1> RTC_50: 			; SET RTC DATE
  3394 00003024 FA                  <1> 	cli
  3395 00003025 E810DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3396 0000302A 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3397 0000302C E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3398                              <1> RTC_55:
  3399 00003031 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3400 00003035 E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3401 0000303A 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3402 0000303C B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3403 0000303E E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3404 00003043 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3405 00003045 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3406 00003047 E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3407 0000304C 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3408 0000304E B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3409 00003050 E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3410 00003055 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3411 00003057 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3412 00003059 E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3413                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3414 0000305E 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3415 00003062 E8BBDAFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3416 00003067 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3417 00003069 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3418 0000306B E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3419 00003070 F8                  <1> 	CLC			; SET CY= 0
  3420 00003071 FB                  <1> 	sti
  3421 00003072 C3                  <1> 	RETn			; RETURN CY=0
  3422                              <1> 
  3423                              <1> 	; 15/03/2015
  3424                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3425 00003073 B426                <1> 	mov	ah, 26h
  3426 00003075 B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3427 00003077 E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3428 0000307C B482                <1> 	mov	ah, 82h
  3429 0000307E B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3430 00003080 E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3431 00003085 B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3432 00003087 E896DAFFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3433 0000308C B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3434                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3435                              <1> 	;RETn
  3436                              <1> 	; 12/02/2022
  3437 0000308E E98FDAFFFF          <1> 	jmp	CMOS_READ
  3438                              <1> 
  3439                              <1> 	; 15/03/2015
  3440                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3441                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3442 00003093 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3443                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3444 00003094 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3445 00003096 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3446 00003097 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3447 00003099 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3448 0000309A E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3449 0000309C 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3450 0000309E E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3451 000030A0 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3452 000030A2 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3453 000030A4 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3454 000030A6 90                  <1> 	nop			; I/O DELAY
  3455 000030A7 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3456                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3457 000030A9 9D                  <1> 	popf	
  3458 000030AA C3                  <1> 	RETn
  3459                              <1> 
  3460                              <1> bf_init:
  3461                              <1> 	; 14/08/2015
  3462                              <1> 	; 02/07/2015
  3463                              <1> 	; 01/07/2015
  3464                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3465                              <1> 	; Buffer (pointer) initialization !
  3466                              <1> 	; 
  3467                              <1> 	; 17/07/2013 - 24/07/2013
  3468                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3469                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3470                              <1> 	;
  3471 000030AB BF[C8650000]        <1> 	mov	edi, bufp 
  3472 000030B0 B8[D0760000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3473 000030B5 29D2                <1> 	sub	edx, edx
  3474 000030B7 FECA                <1> 	dec	dl
  3475 000030B9 31C9                <1> 	xor	ecx, ecx
  3476 000030BB 49                  <1> 	dec	ecx
  3477                              <1> bi0:
  3478 000030BC 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3479 000030C1 AB                  <1> 	stosd
  3480 000030C2 89C6                <1> 	mov	esi, eax
  3481 000030C4 8916                <1> 	mov	[esi], edx ; 000000FFh
  3482                              <1> 			    ; Not a valid device sign
  3483 000030C6 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3484                              <1> 		      ; Not a valid block number sign 	 	
  3485 000030C9 3D[90660000]        <1> 	cmp	eax, buffer
  3486 000030CE 77EC                <1> 	ja	short bi0
  3487 000030D0 B8[D0760000]        <1> 	mov	eax, sb0
  3488 000030D5 AB                  <1> 	stosd
  3489 000030D6 B8[D8780000]        <1> 	mov	eax, sb1
  3490 000030DB AB                  <1> 	stosd
  3491 000030DC 89C6                <1> 	mov	esi, eax ; offset sb1
  3492 000030DE 8916                <1> 	mov	[esi], edx ; 000000FFh
  3493                              <1> 			    ; Not a valid device sign
  3494 000030E0 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3495                              <1> 		      ; Not a valid block number sign 	 
  3496                              <1> 	; 14/08/2015
  3497                              <1> 	;call 	rdev_init
  3498                              <1> 	;retn
  3499                              <1> 
  3500                              <1> rdev_init: ; root device, super block buffer initialization
  3501                              <1> 	; 01/02/2022
  3502                              <1> 	; 14/08/2015
  3503                              <1> 	; Retro UNIX 386 v1 feature only !
  3504                              <1> 	;
  3505                              <1> 	; NOTE: Disk partitions (file systems), logical
  3506                              <1> 	; drive initialization, partition's start sector etc.
  3507                              <1> 	; will be coded here, later in 'ldrv_init'	
  3508                              <1> 
  3509 000030E3 0FB605[685D0000]    <1> 	movzx	eax, byte [boot_drv]
  3510                              <1> rdi_0:
  3511 000030EA 3C80                <1> 	cmp	al, 80h
  3512 000030EC 7202                <1> 	jb	short rdi_1
  3513 000030EE 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3514                              <1> rdi_1:
  3515 000030F0 A2[F6650000]        <1> 	mov	[rdev], al
  3516 000030F5 BB[D0760000]        <1>         mov	ebx, sb0 ; super block buffer
  3517 000030FA 8903                <1> 	mov 	[ebx], eax
  3518 000030FC B001                <1> 	mov	al, 1 ; eax = 1
  3519 000030FE 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3520                              <1> 	;call 	diskio
  3521                              <1> 	;retn
  3522                              <1> 	; 01/02/2022
  3523 00003101 E90B250000          <1> 	jmp	diskio
  3524                              <1> 
  3525                              <1> ; 23/10/2015
  3526                              <1> com1_irq4:
  3527 00003106 [0E310000]          <1> 	dd dummy_retn
  3528                              <1> com2_irq3:
  3529 0000310A [0E310000]          <1> 	dd dummy_retn
  3530                              <1> 
  3531                              <1> dummy_retn:
  3532 0000310E C3                  <1> 	retn
  2050                                  %include 'u1.s'        ; 10/05/2015
  2051                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2052                              <1> ; Last Modification: 27/02/2022
  2053                              <1> ; ----------------------------------------------------------------------------
  2054                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2055                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2056                              <1> ;
  2057                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2058                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2059                              <1> ; <Bell Laboratories (17/3/1972)>
  2060                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2061                              <1> ;
  2062                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2063                              <1> ;
  2064                              <1> ; ****************************************************************************
  2065                              <1> ; 23/11/2015
  2066                              <1> 
  2067                              <1> unkni: ; / used for all system calls
  2068                              <1> sysent: ; < enter to system call >
  2069                              <1> 	; 27/02/2022
  2070                              <1> 	; 01/02/2022
  2071                              <1> 	; 19/10/2015
  2072                              <1> 	; 21/09/2015
  2073                              <1> 	; 01/07/2015
  2074                              <1> 	; 19/05/2015
  2075                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2076                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2077                              <1> 	;
  2078                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2079                              <1> 	; The trap type is determined and an indirect jump is made to 
  2080                              <1> 	; the appropriate system call handler. If there is a trap inside
  2081                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2082                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2083                              <1> 	; instructor is decoded to get the the system code part (see
  2084                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2085                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2086                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2087                              <1> 	; is called. If the call is legitimate control passes to the
  2088                              <1> 	; appropriate system routine.
  2089                              <1> 	;
  2090                              <1> 	; Calling sequence:
  2091                              <1> 	;	Through a trap caused by any sys call outside the system.
  2092                              <1> 	; Arguments:
  2093                              <1> 	;	Arguments of particular system call.	
  2094                              <1> 	; ...............................................................
  2095                              <1> 	;	
  2096                              <1> 	; Retro UNIX 8086 v1 modification: 
  2097                              <1> 	;       System call number is in EAX register.
  2098                              <1> 	;
  2099                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2100                              <1> 	;	registers depending of function details.
  2101                              <1>   	;
  2102                              <1> 	; 16/04/2015
  2103 0000310F 368925[08660000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2104                              <1> 	; save user registers
  2105 00003116 1E                  <1> 	push	ds
  2106 00003117 06                  <1> 	push	es
  2107 00003118 0FA0                <1> 	push	fs
  2108 0000311A 0FA8                <1> 	push	gs
  2109 0000311C 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2110                              <1> 	;
  2111                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2112                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2113                              <1> 	;	for saving/restoring user registers.)
  2114                              <1> 	;
  2115 0000311D 50                  <1> 	push	eax ; 01/07/2015
  2116 0000311E 66B81000            <1> 	mov     ax, KDATA
  2117 00003122 8ED8                <1>         mov     ds, ax
  2118 00003124 8EC0                <1>         mov     es, ax
  2119 00003126 8EE0                <1>         mov     fs, ax
  2120 00003128 8EE8                <1>         mov     gs, ax
  2121 0000312A A1[48620000]        <1> 	mov	eax, [k_page_dir]
  2122 0000312F 0F22D8              <1> 	mov	cr3, eax
  2123 00003132 58                  <1> 	pop	eax ; 01/07/2015
  2124                              <1> 	; 19/10/2015
  2125 00003133 FC                  <1> 	cld
  2126                              <1> 	;
  2127 00003134 FE05[05660000]      <1> 	inc	byte [sysflg]
  2128                              <1> 		; incb sysflg / indicate a system routine is in progress
  2129 0000313A FB                  <1>         sti 	; 18/01/2014
  2130                              <1> 	;jnz	panic ; 24/05/2013
  2131                              <1> 		; beq 1f
  2132                              <1> 		; jmp panic ; / called if trap inside system
  2133                              <1> 	; 01/02/2022
  2134 0000313B 7405                <1> 	jz	short sysent_1
  2135 0000313D E984F9FFFF          <1> 	jmp	panic
  2136                              <1> sysent_1:
  2137                              <1> ;1:	; 16/04/2015
  2138 00003142 A3[10660000]        <1> 	mov	[u.r0], eax
  2139 00003147 8925[0C660000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2140                              <1> 	;
  2141                              <1> 		; mov $s.syst+2,clockp
  2142                              <1> 		; mov r0,-(sp) / save user registers 
  2143                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2144                              <1> 			   ; / in u.r0
  2145                              <1> 		; mov r1,-(sp)
  2146                              <1> 		; mov r2,-(sp)
  2147                              <1> 		; mov r3,-(sp)
  2148                              <1> 		; mov r4,-(sp)
  2149                              <1> 		; mov r5,-(sp)
  2150                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2151                              <1> 		             ; / arithmetic unit
  2152                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2153                              <1> 		             ; / extended arithmetic unit
  2154                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2155                              <1> 		             ; / arithmetic unit
  2156                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2157                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2158                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2159                              <1> 		; sub $sys,r0 / get xxx code
  2160 0000314D C1E002              <1> 	shl	eax, 2
  2161                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2162 00003150 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2163                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2164                              <1> 	;jnb	short badsys
  2165                              <1> 		; bhis badsys / yes, bad system call
  2166                              <1> 	; 27/02/2022
  2167 00003155 7205                <1> 	jb	short _2
  2168 00003157 E954010000          <1> 	jmp	badsys
  2169                              <1> _2:
  2170                              <1> 	; 27/02/2022
  2171                              <1> 	;cmc
  2172                              <1> 	;pushf	
  2173                              <1> 	;push	eax
  2174 0000315C 8B2D[08660000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2175                              <1> 	;mov	al, 0FEh ; 11111110b
  2176                              <1> 	;;adc	al, 0 ; al = al + cf
  2177                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2178 00003162 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2179                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2180                              <1> 				 ; / and clear carry bit
  2181                              <1> 	;pop	ebp ; eax
  2182 00003166 89C5                <1> 	mov	ebp, eax
  2183                              <1> 	;popf
  2184                              <1>         ;;jc	badsys
  2185                              <1> 	; 27/02/2022
  2186                              <1> 	;jnc	short _3
  2187                              <1> 	;jmp	badsys
  2188                              <1> ;_3:
  2189 00003168 A1[10660000]        <1> 	mov	eax, [u.r0]
  2190                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2191 0000316D FFA5[73310000]      <1> 	jmp	dword [ebp+syscalls]
  2192                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2193                              <1> 		            ; / to proper system routine.
  2194                              <1> syscalls: ; 1:
  2195                              <1> 	; 21/09/2015
  2196                              <1> 	; 01/07/2015
  2197                              <1> 	; 16/04/2015 (32 bit address modification) 
  2198 00003173 [7A320000]          <1> 	dd sysrele	; / 0
  2199 00003177 [22330000]          <1> 	dd sysexit 	; / 1
  2200 0000317B [4D340000]          <1> 	dd sysfork 	; / 2
  2201 0000317F [53350000]          <1> 	dd sysread 	; / 3
  2202 00003183 [66350000]          <1> 	dd syswrite 	; / 4
  2203 00003187 [CF350000]          <1> 	dd sysopen 	; / 5
  2204 0000318B [FE360000]          <1> 	dd sysclose 	; / 6
  2205 0000318F [C8330000]          <1> 	dd syswait 	; / 7
  2206 00003193 [7B360000]          <1> 	dd syscreat 	; / 8
  2207 00003197 [B03A0000]          <1> 	dd syslink 	; / 9
  2208 0000319B [6C3B0000]          <1> 	dd sysunlink 	; / 10
  2209 0000319F [333C0000]          <1> 	dd sysexec 	; / 11
  2210 000031A3 [BC420000]          <1> 	dd syschdir 	; / 12
  2211 000031A7 [A1430000]          <1> 	dd systime 	; / 13
  2212 000031AB [B7360000]          <1> 	dd sysmkdir 	; / 14
  2213 000031AF [0E430000]          <1> 	dd syschmod 	; / 15
  2214 000031B3 [71430000]          <1> 	dd syschown 	; / 16
  2215 000031B7 [D4430000]          <1> 	dd sysbreak 	; / 17
  2216 000031BB [F43F0000]          <1> 	dd sysstat 	; / 18
  2217 000031BF [A4440000]          <1> 	dd sysseek 	; / 19
  2218 000031C3 [B6440000]          <1> 	dd systell 	; / 20
  2219 000031C7 [EA4F0000]          <1> 	dd sysmount 	; / 21
  2220 000031CB [D5500000]          <1> 	dd sysumount 	; / 22
  2221 000031CF [32450000]          <1> 	dd syssetuid 	; / 23
  2222 000031D3 [63450000]          <1> 	dd sysgetuid 	; / 24
  2223 000031D7 [B0430000]          <1> 	dd sysstime 	; / 25
  2224 000031DB [26450000]          <1> 	dd sysquit 	; / 26
  2225 000031DF [1A450000]          <1> 	dd sysintr 	; / 27
  2226 000031E3 [D13F0000]          <1> 	dd sysfstat 	; / 28
  2227 000031E7 [16370000]          <1> 	dd sysemt 	; / 29
  2228 000031EB [5E370000]          <1> 	dd sysmdate 	; / 30
  2229 000031EF [B8370000]          <1> 	dd sysstty 	; / 31
  2230 000031F3 [A3390000]          <1> 	dd sysgtty 	; / 32
  2231 000031F7 [59370000]          <1> 	dd sysilgins 	; / 33
  2232 000031FB [33580000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2233                              <1> 			     ; 11/06/2014
  2234 000031FF [4A580000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2235                              <1> 			     ; 01/07/2015
  2236 00003203 [22590000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2237                              <1> 			     ; 21/09/2015 - get last error number
  2238                              <1> end_of_syscalls:
  2239                              <1> 
  2240                              <1> error:
  2241                              <1> 	; 17/09/2015
  2242                              <1> 	; 03/09/2015
  2243                              <1> 	; 01/09/2015
  2244                              <1> 	; 09/06/2015
  2245                              <1> 	; 13/05/2015
  2246                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2247                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2248                              <1> 	;
  2249                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2250                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2251                              <1> 	;
  2252                              <1> 	; INPUTS -> none
  2253                              <1> 	; OUTPUTS ->
  2254                              <1> 	;	processor status - carry (c) bit is set (means error)
  2255                              <1> 	;
  2256                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2257                              <1> 	; 	      Because, jumps to error procedure
  2258                              <1> 	;	      disrupts push-pop nesting balance)
  2259                              <1> 	;
  2260 00003207 8B2D[08660000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2261 0000320D 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2262                              <1> 				 ; (system call will return with cf = 1)
  2263                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2264                              <1> 		               ; / users stack
  2265                              <1> 	; 17/09/2015
  2266 00003211 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2267                              <1> 				 ; for saving/restoring user registers	
  2268                              <1> 	;cmp	ebp, [u.usp]
  2269                              <1> 	;je	short err0	
  2270 00003214 892D[0C660000]      <1> 	mov	[u.usp], ebp
  2271                              <1> ;err0:
  2272                              <1> 	; 01/09/2015
  2273 0000321A 8B25[0C660000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2274                              <1> 				    ; 10/04/2013
  2275                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2276                              <1> 				    ; related procedures will jump to 'error'
  2277                              <1> 				    ; procedure directly without returning to 
  2278                              <1> 				    ; the caller procedure. So, stack pointer
  2279                              <1>                                     ; must be restored here.)
  2280                              <1> 	; 13/05/2015
  2281                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2282                              <1> 	;	'get last error' system call later. 	
  2283                              <1> 
  2284                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2285 00003220 C605[71660000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2286                              <1> 
  2287                              <1> sysret: ; < return from system call>
  2288                              <1> 	; 01/02/2022
  2289                              <1> 	; 10/09/2015
  2290                              <1> 	; 29/07/2015
  2291                              <1> 	; 25/06/2015
  2292                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2293                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2294                              <1> 	;
  2295                              <1> 	; 'sysret' first checks to see if process is about to be 
  2296                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2297                              <1> 	; If not, following happens:	 
  2298                              <1> 	; 	1) The user's stack pointer is restored.
  2299                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2300                              <1> 	;	   i-node has been modified. If it has, it is written out
  2301                              <1> 	;	   via 'ppoke'.
  2302                              <1> 	;	3) If the super block has been modified, it is written out
  2303                              <1> 	;	   via 'ppoke'.				
  2304                              <1> 	;	4) If the dismountable file system's super block has been
  2305                              <1> 	;	   modified, it is written out to the specified device
  2306                              <1> 	;	   via 'ppoke'.
  2307                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2308                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2309                              <1> 	;	   another user a chance to run.
  2310                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2311                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2312                              <1> 	;
  2313                              <1> 	; Calling sequence:
  2314                              <1> 	;	jump table or 'br sysret'
  2315                              <1> 	; Arguments: 
  2316                              <1> 	;	-	
  2317                              <1> 	; ...............................................................
  2318                              <1> 	;	
  2319                              <1> 	; ((AX=r1 for 'iget' input))
  2320                              <1> 	;	
  2321                              <1> 	;xor	ax, ax ; 04/05/2013
  2322                              <1> 	; 01/02/2022
  2323 00003227 31C0                <1> 	xor	eax, eax
  2324                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2325 00003229 FEC0                <1> 	inc	al ; 04/05/2013
  2326 0000322B 3805[58660000]      <1> 	cmp	[u.bsys], al ; 1
  2327                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2328                              <1>         ;jnb	sysexit ; 04/05/2013
  2329                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2330                              <1> 	; 01/02/2022
  2331 00003231 7205                <1> 	jb	short sysret_2
  2332 00003233 E9EA000000          <1> 	jmp	sysexit
  2333                              <1> sysret_2:
  2334                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2335                              <1> 		; mov u.sp,sp / no point stack to users stack
  2336 00003238 FEC8                <1> 	dec 	al ; mov ax, 0
  2337                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2338 0000323A E8DE160000          <1> 	call	iget
  2339                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2340                              <1> 		            ; / it is written out
  2341 0000323F 6631C0              <1> 	xor 	ax, ax ; 0
  2342 00003242 3805[03660000]      <1> 	cmp	[smod], al ; 0
  2343                              <1> 		; tstb	smod / has the super block been modified
  2344 00003248 7614                <1> 	jna	short sysret1
  2345                              <1> 		; beq	1f / no, 1f
  2346 0000324A A2[03660000]        <1> 	mov	[smod], al ; 0
  2347                              <1> 		; clrb smod / yes, clear smod
  2348 0000324F BB[D0760000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2349 00003254 66810B0002          <1>    	or	word [ebx], 200h ;;
  2350                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2351                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2352                              <1> 		      	      ; / output
  2353                              <1> 	; AX = 0
  2354 00003259 E817230000          <1> 	call 	poke ; 07/08/2013
  2355                              <1> 	;call	ppoke
  2356                              <1> 	; AX = 0
  2357                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2358                              <1> sysret1: ;1:
  2359 0000325E 3805[04660000]      <1> 	cmp	[mmod], al ; 0
  2360                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2361                              <1> 		           ; / system
  2362 00003264 7614                <1> 	jna	short sysrel0
  2363                              <1> 		; beq 1f / been modified?  no, 1f
  2364 00003266 A2[04660000]        <1> 	mov	[mmod], al ; 0	
  2365                              <1> 		; clrb	mmod / yes, clear mmod
  2366                              <1>         ;mov    ax, [mntd]
  2367                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2368 0000326B BB[D8780000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2369                              <1>         ;;mov	[ebx], al
  2370                              <1> 	;mov    [sb1], al
  2371                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2372 00003270 66810B0002          <1> 	or	word [ebx], 200h
  2373                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2374                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2375 00003275 E8FB220000          <1> 	call	poke ; 07/08/2013
  2376                              <1> 	;call	ppoke 
  2377                              <1> 		; jsr r0,ppoke / write it out to its device
  2378                              <1>         ;xor    al, al ; 26/04/2013       
  2379                              <1> ;1:
  2380                              <1> 		; tstb uquant / is the time quantum 0?
  2381                              <1> 		; bne 1f / no, don't swap it out
  2382                              <1> 
  2383                              <1> sysrele: ; < release >
  2384                              <1> 	; 14/10/2015
  2385                              <1> 	; 01/09/2015
  2386                              <1> 	; 24/07/2015
  2387                              <1> 	; 14/05/2015
  2388                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2389                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2390                              <1> 	;
  2391                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2392                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2393                              <1> 	; turns off the system flag. It then checked to see if there is
  2394                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2395                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2396                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2397                              <1> 	; the user, a rti is made.
  2398                              <1> 	;
  2399                              <1> 	; Calling sequence:
  2400                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2401                              <1> 	; Arguments:
  2402                              <1> 	;	-	
  2403                              <1> 	; ...............................................................
  2404                              <1> 	;	
  2405                              <1> 	; 23/02/2014 (swapret)
  2406                              <1> 	; 22/09/2013
  2407                              <1> sysrel0: ;1:
  2408 0000327A 803D[4C660000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2409                              <1> 		; tstb uquant / is the time quantum 0?
  2410 00003281 7705                <1>         ja      short swapret
  2411                              <1> 		; bne 1f / no, don't swap it out
  2412                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2413 00003283 E82B130000          <1> 	call	tswap
  2414                              <1> 		; jsr r0,tswap / yes, swap it out
  2415                              <1> ;
  2416                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2417                              <1> swapret: ;1:
  2418                              <1> 	; 10/09/2015
  2419                              <1> 	; 01/09/2015
  2420                              <1> 	; 14/05/2015
  2421                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2422                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2423                              <1> 	; cli
  2424                              <1> 	; 24/07/2015
  2425                              <1> 	;
  2426                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2427                              <1> 	;; mov	esp, [u.usp]
  2428                              <1> 
  2429                              <1> 	; 22/09/2013
  2430 00003288 E8FD140000          <1> 	call	isintr
  2431                              <1> 	; 20/10/2013
  2432 0000328D 7405                <1> 	jz	short sysrel1
  2433 0000328F E877000000          <1> 	call	intract
  2434                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2435                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2436                              <1> 		               ; / action
  2437                              <1> sysrel1:
  2438 00003294 FA                  <1> 	cli ; 14/10/2015
  2439 00003295 FE0D[05660000]      <1> 	dec	byte [sysflg]
  2440                              <1> 		; decb sysflg / turn system flag off
  2441 0000329B A1[63660000]        <1> 	mov     eax, [u.pgdir]
  2442 000032A0 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2443                              <1> 			  ; (others are different than kernel page tables) 
  2444                              <1> 	; 10/09/2015
  2445 000032A3 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2446                              <1> 		; mov (sp)+,sc / restore user registers
  2447                              <1> 		; mov (sp)+,mq
  2448                              <1> 		; mov (sp)+,ac
  2449                              <1> 		; mov (sp)+,r5
  2450                              <1> 		; mov (sp)+,r4
  2451                              <1> 		; mov (sp)+,r3
  2452                              <1> 		; mov (sp)+,r2
  2453                              <1> 	;
  2454 000032A4 A1[10660000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2455 000032A9 0FA9                <1> 	pop	gs
  2456 000032AB 0FA1                <1> 	pop	fs
  2457 000032AD 07                  <1> 	pop	es
  2458 000032AE 1F                  <1> 	pop	ds
  2459 000032AF CF                  <1> 	iretd	
  2460                              <1> 		; rti / no, return from interrupt
  2461                              <1> 
  2462                              <1> badsys:
  2463                              <1> 	; 27/02/2022
  2464                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2465                              <1> 	; (Major Modification: 'core' dumping procedure in
  2466                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2467                              <1> 	;	has been changed to print 'Invalid System Call !'
  2468                              <1> 	;	message on the user's console tty.)
  2469                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2470                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2471                              <1> 	; (EAX = Function number)  
  2472                              <1> 	;
  2473 000032B0 FE05[58660000]      <1> 	inc	byte [u.bsys]
  2474                              <1> 	;
  2475 000032B6 8B1D[08660000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2476 000032BC 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2477 000032BE E827E4FFFF          <1> 	call	dwordtohex
  2478 000032C3 8915[A65F0000]      <1> 	mov	[bsys_msg_eip], edx
  2479 000032C9 A3[AA5F0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2480 000032CE A1[10660000]        <1> 	mov	eax, [u.r0]
  2481 000032D3 E812E4FFFF          <1> 	call	dwordtohex
  2482 000032D8 8915[965F0000]      <1> 	mov	[bsys_msg_eax], edx
  2483 000032DE A3[9A5F0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2484                              <1> 	; 27/02/2022
  2485                              <1> 	;xor	eax, eax
  2486                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2487                              <1> 	;mov	ebx, [u.fofp]
  2488                              <1> 	;mov	[ebx], eax
  2489                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2490                              <1> 	;inc	eax
  2491                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2492                              <1> 		; writei
  2493                              <1> 		; INPUTS ->
  2494                              <1> 		;    r1 - inode number
  2495                              <1> 		;    u.count - byte count to be written
  2496                              <1> 		;    u.base - points to user buffer
  2497                              <1> 		;    u.fofp - points to word with current file offset
  2498                              <1> 		; OUTPUTS ->
  2499                              <1> 		;    u.count - cleared
  2500                              <1> 		;    u.nread - accumulates total bytes passed back	
  2501                              <1> 		;
  2502                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2503                              <1> 	;call	writei
  2504                              <1> 	;;mov	eax, 1
  2505                              <1> 	;jmp	sysexit
  2506                              <1> 
  2507                              <1> 	; 27/02/2022
  2508 000032E3 BE[775F0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2509 000032E8 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2510 000032EF 8A83[63630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2511 000032F5 C605[77620000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2512 000032FC A2[5E660000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2513 00003301 E801260000          <1> 	call	print_cmsg
  2514                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2515 00003306 E9FCFEFFFF          <1> 	jmp	error
  2516                              <1> 
  2517                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2518                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2519                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2520                              <1> 		; br 1f / error
  2521                              <1> 		; neg r1 / negate the i-number to open the core image file
  2522                              <1> 		       ; / for writing
  2523                              <1> 		; jsr r0,iopen / open the core image file
  2524                              <1> 		; jsr r0,itrunc / free all associated blocks
  2525                              <1> 		; br 2f
  2526                              <1> ;1:
  2527                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2528                              <1> 		; jsr r0,maknod / make an i-node
  2529                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2530                              <1> ;2:
  2531                              <1> 		; mov $core,u.base / move address core to u.base
  2532                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2533                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2534                              <1> 		; clr u.off / clear user offset
  2535                              <1> 		; jsr r0,writei / write out the core image to the user
  2536                              <1> 		; mov $user,u.base / pt. u.base to user
  2537                              <1> 		; mov $64.,u.count / u.count = 64
  2538                              <1> 		; jsr r0,writei / write out all the user parameters
  2539                              <1> 		; neg r1 / make i-number positive
  2540                              <1> 		; jsr r0,iclose / close the core image file
  2541                              <1> 		; br sysexit /
  2542                              <1> ;3:
  2543                              <1> 		; <core\0\0>
  2544                              <1> 
  2545                              <1> intract: ; / interrupt action
  2546                              <1> 	; 14/10/2015
  2547                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2548                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2549                              <1> 	;
  2550                              <1> 	; Retro UNIX 8086 v1 modification !
  2551                              <1> 	; (Process/task switching and quit routine by using
  2552                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2553                              <1> 	;
  2554                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2555                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2556                              <1> 	;		'intract' will jump to 'sysexit'.
  2557                              <1> 	;	    Intract will return to the caller 
  2558                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2559                              <1> 	; 14/10/2015
  2560 0000330B FB                  <1> 	sti
  2561                              <1> 	; 07/12/2013	
  2562 0000330C 66FF05[50660000]    <1> 	inc 	word [u.quit]
  2563 00003313 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2564 00003315 66FF0D[50660000]    <1> 	dec	word [u.quit]
  2565                              <1> 	; 16/04/2015
  2566 0000331C C3                  <1> 	retn
  2567                              <1> intrct0:	
  2568 0000331D 58                  <1> 	pop	eax ; call intract -> retn
  2569                              <1> 	;
  2570 0000331E 31C0                <1> 	xor 	eax, eax
  2571 00003320 FEC0                <1> 	inc	al  ; mov ax, 1
  2572                              <1> ;;;
  2573                              <1> 	; UNIX v1 original 'intract' routine... 
  2574                              <1> 	; / interrupt action
  2575                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2576                              <1> 		; bne 1f / no, 1f
  2577                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2578                              <1> 	; 1: / now in user area
  2579                              <1> 		; mov r1,-(sp) / save r1
  2580                              <1> 		; mov u.ttyp,r1 
  2581                              <1> 			; / pointer to tty buffer in control-to r1
  2582                              <1> 		; cmpb 6(r1),$177
  2583                              <1> 			; / is the interrupt char equal to "del"
  2584                              <1> 		; beq 1f / yes, 1f
  2585                              <1> 		; clrb 6(r1) 
  2586                              <1> 		        ; / no, clear the byte 
  2587                              <1> 			; / (must be a quit character)
  2588                              <1> 		; mov (sp)+,r1 / restore r1
  2589                              <1> 		; clr u.quit / clear quit flag
  2590                              <1> 		; bis $20,2(sp) 
  2591                              <1> 		    	; / set trace for quit (sets t bit of 
  2592                              <1> 			; / ps-trace trap)
  2593                              <1> 		; rti   ;  / return from interrupt
  2594                              <1> 	; 1: / interrupt char = del
  2595                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2596                              <1> 			   ; / in the buffer
  2597                              <1> 		; mov (sp)+,r1 / restore r1
  2598                              <1> 		; cmp u.intr,$core / should control be 
  2599                              <1> 				; / transferred to loc core?
  2600                              <1> 		; blo 1f
  2601                              <1> 		; jmp *u.intr / user to do rti yes, 
  2602                              <1> 				; / transfer to loc core
  2603                              <1> 	; 1:
  2604                              <1> 		; sys 1 / exit
  2605                              <1> 
  2606                              <1> sysexit: ; <terminate process>
  2607                              <1> 	; 01/02/2022
  2608                              <1> 	; 01/09/2015
  2609                              <1> 	; 31/08/2015
  2610                              <1> 	; 14/05/2015
  2611                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2612                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2613                              <1> 	;
  2614                              <1> 	; 'sysexit' terminates a process. First each file that
  2615                              <1> 	; the process has opened is closed by 'flose'. The process
  2616                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2617                              <1> 	; searched to find children of the dying process. If any of
  2618                              <1> 	; children are zombies (died by not waited for), they are
  2619                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2620                              <1> 	; dying process's parent. When the parent is found, it is
  2621                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2622                              <1> 	; one of these, the dying process just dies. If it is waiting
  2623                              <1> 	; for a child process to die, it notified that it doesn't 
  2624                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2625                              <1> 	; (waiting to active). It is awakened and put on runq by
  2626                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2627                              <1> 	; it will never be run again but stays around until a 'wait'
  2628                              <1> 	; is completed by it's parent process. If the parent is not
  2629                              <1> 	; found, process just dies. This means 'swap' is called with
  2630                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2631                              <1> 	; to write out the process and 'rswap' reads the new process
  2632                              <1> 	; over the one that dies..i.e., the dying process is 
  2633                              <1> 	; overwritten and destroyed.	
  2634                              <1>  	;
  2635                              <1> 	; Calling sequence:
  2636                              <1> 	;	sysexit or conditional branch.
  2637                              <1> 	; Arguments:
  2638                              <1> 	;	-	
  2639                              <1> 	; ...............................................................
  2640                              <1> 	;	
  2641                              <1> 	; Retro UNIX 8086 v1 modification: 
  2642                              <1> 	;       System call number (=1) is in EAX register.
  2643                              <1> 	;
  2644                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2645                              <1> 	;       registers depending of function details.
  2646                              <1> 	;
  2647                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2648                              <1> 	;
  2649                              <1> ; / terminate process
  2650                              <1> 	; AX = 1
  2651                              <1> 	;dec 	ax ; 0
  2652                              <1> 	; 01/02/2022
  2653 00003322 48                  <1> 	dec	eax ; 0
  2654 00003323 66A3[4E660000]      <1> 	mov	[u.intr], ax ; 0
  2655                              <1> 		; clr u.intr / clear interrupt control word
  2656                              <1> 		; clr r1 / clear r1
  2657                              <1> 	; AX = 0
  2658                              <1> sysexit_1: ; 1:
  2659                              <1> 	; AX = File descriptor
  2660                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2661                              <1> 		; / Search the whole list
  2662 00003329 E8640D0000          <1> 	call	fclose
  2663                              <1> 		; jsr r0,fclose / close all files the process opened
  2664                              <1> 	;; ignore error return
  2665                              <1> 		; br .+2 / ignore error return
  2666                              <1> 	;inc	ax
  2667 0000332E FEC0                <1> 	inc	al
  2668                              <1> 		; inc r1 / increment file descriptor
  2669                              <1> 	;cmp	ax, 10
  2670 00003330 3C0A                <1> 	cmp	al, 10
  2671                              <1> 		; cmp r1,$10. / end of u.fp list?
  2672 00003332 72F5                <1> 	jb	short sysexit_1
  2673                              <1> 		; blt 1b / no, go back
  2674 00003334 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2675                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2676 0000333B 88A3[83630000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2677                              <1> 		; clrb p.stat-1(r1) / free the process
  2678                              <1> 	;shl	bx, 1
  2679 00003341 D0E3                <1> 	shl	bl, 1
  2680                              <1> 		; asl r1 / use r1 for index into the below tables
  2681 00003343 668B8B[22630000]    <1> 	mov	cx, [ebx+p.pid-2]
  2682                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2683 0000334A 668B93[42630000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2684                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2685                              <1> 	;xor 	bx, bx ; 0
  2686 00003351 30DB                <1> 	xor	bl, bl ; 0
  2687                              <1> 		; clr r2
  2688 00003353 31F6                <1> 	xor	esi, esi ; 0
  2689                              <1> 		; clr r5 / initialize reg
  2690                              <1> sysexit_2: ; 1:
  2691                              <1> 	        ; / find children of this dying process, 
  2692                              <1> 		; / if they are zombies, free them
  2693                              <1> 	;add	bx, 2
  2694 00003355 80C302              <1> 	add	bl, 2
  2695                              <1> 		; add $2,r2 / search parent process table 
  2696                              <1> 		          ; / for dying process's name
  2697 00003358 66398B[42630000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2698                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2699 0000335F 7513                <1> 	jne	short sysexit_4
  2700                              <1> 		; bne 3f / no
  2701                              <1> 	;shr	bx, 1
  2702 00003361 D0EB                <1> 	shr	bl, 1
  2703                              <1> 		; asr r2 / yes, it is a parent
  2704 00003363 80BB[83630000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2705                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2706                              <1> 				     ; / dying process a zombie
  2707 0000336A 7506                <1> 	jne	short sysexit_3 
  2708                              <1> 		; bne 2f / no
  2709 0000336C 88A3[83630000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2710                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2711                              <1> sysexit_3: ; 2:
  2712                              <1> 	;shr	bx, 1
  2713 00003372 D0E3                <1> 	shl	bl, 1
  2714                              <1> 		; asl r2
  2715                              <1> sysexit_4: ; 3:
  2716                              <1> 		; / search the process name table 
  2717                              <1> 		; / for the dying process's parent
  2718 00003374 663993[22630000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2719                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2720 0000337B 7502                <1> 	jne	short sysexit_5
  2721                              <1> 		; bne 3f / no
  2722 0000337D 89DE                <1> 	mov	esi, ebx
  2723                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2724                              <1> 		          ; / process # x2) in r5
  2725                              <1> sysexit_5: ; 3:
  2726                              <1> 	;cmp	bx, nproc + nproc
  2727 0000337F 80FB20              <1> 	cmp	bl, nproc + nproc
  2728                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2729 00003382 72D1                <1> 	jb	short sysexit_2
  2730                              <1> 		; blt 1b / no, go back
  2731                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2732 00003384 21F6                <1> 	and	esi, esi ; r5=r1
  2733 00003386 7431                <1> 	jz	short sysexit_6
  2734                              <1> 		; beq 2f / no parent has been found. 
  2735                              <1> 		       ; / The process just dies
  2736 00003388 66D1EE              <1> 	shr	si, 1
  2737                              <1> 		; asr r1 / set up index to p.stat
  2738 0000338B 8A86[83630000]      <1> 	mov	al, [esi+p.stat-1]
  2739                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2740 00003391 20C0                <1> 	and	al, al
  2741 00003393 7424                <1> 	jz	short sysexit_6
  2742                              <1> 		; beq 2f / if its been freed, 2f
  2743 00003395 3C03                <1> 	cmp	al, 3
  2744                              <1> 		; cmp r2,$3 / is parent a zombie?
  2745 00003397 7420                <1> 	je	short sysexit_6
  2746                              <1> 		; beq 2f / yes, 2f
  2747                              <1> 	; BH = 0
  2748 00003399 8A1D[59660000]      <1> 	mov	bl, [u.uno]
  2749                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2750 0000339F C683[83630000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2751                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2752                              <1> 	; 05/02/2014
  2753 000033A6 3C01                <1> 	cmp	al, 1 ; SRUN
  2754 000033A8 740F                <1> 	je	short sysexit_6
  2755                              <1> 	;cmp	al, 2
  2756                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2757                              <1> 			  ; / this child to die
  2758                              <1> 	;jne	short sysexit_6	
  2759                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2760                              <1> 	; 05/02/2014
  2761                              <1> 	; p.stat = 2 --> waiting
  2762                              <1> 	; p.stat = 4 --> sleeping
  2763 000033AA C686[83630000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2764                              <1> 	;dec	byte [esi+p.stat-1]
  2765                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2766 000033B1 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2767                              <1> 	; 
  2768                              <1> 	;mov	ebx, runq + 4
  2769                              <1> 		; mov $runq+4,r2 / on the runq
  2770 000033B4 E8D1120000          <1> 	call	putlu
  2771                              <1> 		; jsr r0, putlu
  2772                              <1> sysexit_6: ; 2:
  2773                              <1> 	; 31/08/2015
  2774                              <1> 		; / the process dies
  2775 000033B9 C605[59660000]00    <1> 	mov	byte [u.uno], 0
  2776                              <1> 		; clrb u.uno / put zero as the process number, 
  2777                              <1> 	           ; / so "swap" will
  2778 000033C0 E8F8110000          <1> 	call	swap
  2779                              <1> 		; jsr r0,swap / overwrite process with another process
  2780                              <1> hlt_sys:
  2781                              <1> 	;sti ; 18/01/2014
  2782                              <1> hlts0:
  2783 000033C5 F4                  <1> 	hlt
  2784 000033C6 EBFD                <1> 	jmp	short hlts0
  2785                              <1> 		; 0 / and thereby kill it; halt?
  2786                              <1> 
  2787                              <1> 
  2788                              <1> syswait: ; < wait for a processs to die >
  2789                              <1> 	; 12/02/2022
  2790                              <1> 	; 01/02/2022
  2791                              <1> 	; 17/09/2015
  2792                              <1> 	; 02/09/2015
  2793                              <1> 	; 01/09/2015
  2794                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2795                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2796                              <1> 	;
  2797                              <1> 	; 'syswait' waits for a process die. 
  2798                              <1> 	; It works in following way:
  2799                              <1> 	;    1) From the parent process number, the parent's 
  2800                              <1> 	; 	process name is found. The p.ppid table of parent
  2801                              <1> 	;	names is then searched for this process name.
  2802                              <1> 	;	If a match occurs, r2 contains child's process
  2803                              <1> 	;	number. The child status is checked to see if it is
  2804                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2805                              <1> 	;	If it is, the child process is freed and it's name
  2806                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2807                              <1> 	;	If the child is not a zombie, nothing happens and
  2808                              <1> 	;	the search goes on through the p.ppid table until
  2809                              <1> 	;	all processes are checked or a zombie is found.
  2810                              <1> 	;    2) If no zombies are found, a check is made to see if
  2811                              <1> 	;	there are any children at all. If there are none,
  2812                              <1> 	;	an error return is made. If there are, the parent's
  2813                              <1> 	;	status is set to 2 (waiting for child to die),
  2814                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2815                              <1> 	;	is made to wait on the next process.
  2816                              <1> 	;
  2817                              <1> 	; Calling sequence:
  2818                              <1> 	;	?
  2819                              <1> 	; Arguments:
  2820                              <1> 	;	-
  2821                              <1> 	; Inputs: - 
  2822                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2823                              <1> 	; ...............................................................
  2824                              <1> 	;				
  2825                              <1> 	
  2826                              <1> ; / wait for a process to die
  2827                              <1> 
  2828                              <1> syswait_0:
  2829 000033C8 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2830                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2831 000033CF D0E3                <1> 	shl	bl, 1
  2832                              <1> 	;shl	bx, 1
  2833                              <1> 		; asl r1 / x2 to get index into p.pid table
  2834 000033D1 668B83[22630000]    <1> 	mov	ax, [ebx+p.pid-2]
  2835                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2836 000033D8 31F6                <1> 	xor	esi, esi
  2837                              <1> 		; clr r2
  2838 000033DA 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2839                              <1> 	;xor 	cl, cl
  2840                              <1> 		; clr r3 / initialize reg 3
  2841                              <1> syswait_1: ; 1:
  2842                              <1> 	; 12/02/2022
  2843 000033DC 46                  <1> 	inc	esi
  2844 000033DD 46                  <1> 	inc	esi
  2845                              <1> 	;add	si, 2
  2846                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2847                              <1> 			  ; / search table of parent processes 
  2848                              <1> 			  ; / for this process name
  2849 000033DE 663B86[42630000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2850                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2851                              <1> 			            ; / process number
  2852 000033E5 7531                <1> 	jne	short syswait_3
  2853                              <1> 		; bne 3f / branch if no match of parent process name
  2854                              <1> 	;inc	cx
  2855 000033E7 FEC1                <1> 	inc	cl
  2856                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2857                              <1> 	; 12/02/2022
  2858 000033E9 D1EE                <1> 	shr	esi, 1
  2859                              <1> 	;shr	si, 1
  2860                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2861                              <1> 	; The possible states ('p.stat' values) of a process are:
  2862                              <1> 	;	0 = free or unused
  2863                              <1> 	;	1 = active
  2864                              <1> 	;	2 = waiting for a child process to die
  2865                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2866 000033EB 80BE[83630000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2867                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2868 000033F2 7522                <1> 	jne	short syswait_2
  2869                              <1> 		; bne 2f / no, skip it
  2870 000033F4 88BE[83630000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2871                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2872                              <1> 	; 12/02/2022
  2873 000033FA D1E6                <1> 	shl	esi, 1
  2874                              <1> 	;shl	si, 1
  2875                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2876 000033FC 0FB786[22630000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2877 00003403 A3[10660000]        <1> 	mov	[u.r0], eax
  2878                              <1> 		; mov p.pid-2(r2),*u.r0 
  2879                              <1> 			      ; / put childs process name in (u.r0)
  2880                              <1> 	;
  2881                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2882                              <1> 	;
  2883                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2884                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2885                              <1> 	; system call loop from the application/program if it calls
  2886                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2887                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2888                              <1> 	;
  2889                              <1> 	; Note: syswait will return with error if there is not a
  2890                              <1> 	;       zombie or running process to wait.	
  2891                              <1> 	;
  2892                              <1> 	;sub	ax, ax
  2893                              <1> 	; 01/02/2022
  2894 00003408 29C0                <1> 	sub	eax, eax
  2895 0000340A 668986[42630000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2896 00003411 E913FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2897                              <1> 	;
  2898                              <1> 	;jmp	sysret
  2899                              <1> 		; br sysret1 / return cause child is dead
  2900                              <1> syswait_2: ; 2:
  2901                              <1> 	; 12/02/2022
  2902 00003416 D1E6                <1> 	shl	esi, 1
  2903                              <1> 	;shl	si, 1
  2904                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2905                              <1> syswait_3: ; 3:
  2906 00003418 6683FE20            <1> 	cmp	si, nproc+nproc
  2907                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2908 0000341C 72BE                <1> 	jb	short syswait_1
  2909                              <1> 		; blt 1b / no, continue search
  2910                              <1> 	;and	cx, cx
  2911 0000341E 20C9                <1> 	and	cl, cl
  2912                              <1> 		; tst r3 / one gets here if there are no children 
  2913                              <1> 		       ; / or children that are still active
  2914                              <1> 	; 30/10/2013
  2915 00003420 7515                <1> 	jnz	short syswait_4
  2916                              <1> 	;jz	error
  2917                              <1> 		; beq error1 / there are no children, error
  2918 00003422 890D[10660000]      <1> 	mov	[u.r0], ecx ; 0
  2919                              <1> 	; 12/02/2022
  2920 00003428 C705[5F660000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2920 00003430 0000                <1>
  2921                              <1> 			; miscellaneous/other errors
  2922 00003432 E9D0FDFFFF          <1> 	jmp	error
  2923                              <1> syswait_4:
  2924 00003437 8A1D[59660000]      <1> 	mov	bl, [u.uno]
  2925                              <1> 		; movb u.uno,r1 / there are children so put 
  2926                              <1> 			      ; / parent process number in r1
  2927 0000343D FE83[83630000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2928                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2929                              <1> 				  ; / other children to die
  2930                              <1> 	; 04/11/2013
  2931 00003443 E875110000          <1> 	call	swap
  2932                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2933 00003448 E97BFFFFFF          <1> 	jmp	syswait_0
  2934                              <1> 		; br syswait / wait on next process
  2935                              <1> 
  2936                              <1> sysfork: ; < create a new process >
  2937                              <1> 	; 26/02/2022
  2938                              <1> 	; 25/02/2022
  2939                              <1> 	; 01/02/2022
  2940                              <1> 	; 18/09/2015
  2941                              <1> 	; 04/09/2015
  2942                              <1> 	; 02/09/2015
  2943                              <1> 	; 01/09/2015
  2944                              <1> 	; 28/08/2015
  2945                              <1> 	; 14/05/2015
  2946                              <1> 	; 10/05/2015
  2947                              <1> 	; 09/05/2015
  2948                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2949                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2950                              <1> 	;
  2951                              <1> 	; 'sysfork' creates a new process. This process is referred
  2952                              <1> 	; to as the child process. This new process core image is
  2953                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2954                              <1> 	; distinction is the return location and the fact that (u.r0)
  2955                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2956                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2957                              <1> 	; 'sysfork' works in the following manner: 	
  2958                              <1> 	;    1) The process status table (p.stat) is searched to find
  2959                              <1> 	;	a process number that is unused. If none are found
  2960                              <1> 	;	an error occurs.
  2961                              <1> 	;    2) when one is found, it becomes the child process number
  2962                              <1> 	;	and it's status (p.stat) is set to active.
  2963                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2964                              <1> 	;	character in that tty buffer is cleared.
  2965                              <1> 	;    4) The child process is put on the lowest priority run 
  2966                              <1> 	;	queue via 'putlu'.
  2967                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2968                              <1> 	;	it is a unique number) and is put in the child's unique
  2969                              <1> 	;	identifier; process id (p.pid).
  2970                              <1> 	;    6) The process name of the parent is then obtained and
  2971                              <1> 	;	placed in the unique identifier of the parent process
  2972                              <1> 	;	name is then put in 'u.r0'.	
  2973                              <1> 	;    7) The child process is then written out on disk by
  2974                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2975                              <1> 	;	and the child is born. (The child process is written 
  2976                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2977                              <1> 	;	number.)
  2978                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2979                              <1> 	;    9) The child process name is put in 'u.r0'.
  2980                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2981                              <1> 	;	create the return address for the parent process.
  2982                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2983                              <1> 	;	the parent has opened. For each file the parent has
  2984                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2985                              <1> 	;	to indicate that the child process also has opened
  2986                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2987                              <1> 	;
  2988                              <1> 	; Calling sequence:
  2989                              <1> 	;	from shell ?
  2990                              <1> 	; Arguments:
  2991                              <1> 	;	-
  2992                              <1> 	; Inputs: -
  2993                              <1> 	; Outputs: *u.r0 - child process name
  2994                              <1> 	; ...............................................................
  2995                              <1> 	;	
  2996                              <1> 	; Retro UNIX 8086 v1 modification: 
  2997                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2998                              <1> 	;	= process id of child a parent process returns
  2999                              <1> 	;	= process id of parent when a child process returns
  3000                              <1> 	;
  3001                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3002                              <1> 	;	in following manner: (with an example: c library, fork)
  3003                              <1> 	;	
  3004                              <1> 	;	1:
  3005                              <1> 	;		sys	fork
  3006                              <1> 	;			br 1f  / child process returns here
  3007                              <1> 	;		bes	2f     / parent process returns here
  3008                              <1> 	;		/ pid of new process in r0
  3009                              <1> 	;		rts	pc
  3010                              <1> 	;	2: / parent process condionally branches here
  3011                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3012                              <1> 	;		rts	pc
  3013                              <1> 	;
  3014                              <1> 	;	1: / child process brances here
  3015                              <1> 	;		clr	r0   / pid = 0 in child process
  3016                              <1> 	;		rts	pc
  3017                              <1> 	;
  3018                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3019                              <1> 	;		// pid = fork();
  3020                              <1> 	;		//
  3021                              <1> 	;		// pid == 0 in child process; 
  3022                              <1> 	;		// pid == -1 means error return
  3023                              <1> 	;		// in child, 
  3024                              <1> 	;		//	parents id is in par_uid if needed
  3025                              <1> 	;		
  3026                              <1> 	;		_fork:
  3027                              <1> 	;			mov	$.fork,eax
  3028                              <1> 	;			int	$0x30
  3029                              <1> 	;			jmp	1f
  3030                              <1> 	;			jnc	2f
  3031                              <1> 	;			jmp	cerror
  3032                              <1> 	;		1:
  3033                              <1> 	;			mov	eax,_par_uid
  3034                              <1> 	;			xor	eax,eax
  3035                              <1> 	;		2:
  3036                              <1> 	;			ret
  3037                              <1> 	;
  3038                              <1> 	;	In Retro UNIX 8086 v1,
  3039                              <1> 	;	'sysfork' returns in following manner:
  3040                              <1> 	;	
  3041                              <1> 	;		mov	ax, sys_fork
  3042                              <1> 	;		mov	bx, offset @f ; routine for child
  3043                              <1> 	;		int	20h
  3044                              <1> 	;		jc	error
  3045                              <1> 	;		
  3046                              <1> 	;	; Routine for parent process here (just after 'jc')
  3047                              <1> 	;		mov	word ptr [pid_of_child], ax
  3048                              <1> 	;		jmp	next_routine_for_parent	
  3049                              <1> 	;
  3050                              <1> 	;	@@: ; routine for child process here				
  3051                              <1> 	;		....	
  3052                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3053                              <1> 	;	       for child process by using BX input.
  3054                              <1> 	;	      (at first, parent process will return then 
  3055                              <1> 	;	      child process will return -after swapped in-
  3056                              <1> 	;	      'syswait' is needed in parent process
  3057                              <1> 	;	      if return from child process will be waited for.)
  3058                              <1> 	;	  				
  3059                              <1> 	
  3060                              <1> ; / create a new process
  3061                              <1> 	; EBX = return address for child process 
  3062                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3063 0000344D 31F6                <1> 	xor 	esi, esi
  3064                              <1> 		; clr r1
  3065                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3066 0000344F 46                  <1> 	inc	esi
  3067                              <1> 		; inc r1
  3068 00003450 80BE[83630000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3069                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3070 00003457 760B                <1> 	jna	short sysfork_2	
  3071                              <1> 		; beq 1f / it's unused so branch
  3072 00003459 6683FE10            <1> 	cmp	si, nproc
  3073                              <1> 		; cmp r1,$nproc / all processes checked
  3074 0000345D 72F0                <1> 	jb	short sysfork_1
  3075                              <1> 		; blt 1b / no, branch back
  3076                              <1> 	;
  3077                              <1> 	; Retro UNIX 8086 v1. modification:
  3078                              <1> 	;	Parent process returns from 'sysfork' to address 
  3079                              <1> 	;	which is just after 'sysfork' system call in parent
  3080                              <1> 	;	process. Child process returns to address which is put
  3081                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3082                              <1> 	;
  3083                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3084                              <1> 		               ; / to old process return
  3085                              <1> 		; br error1 / no room for a new process
  3086                              <1> sysfork_err:
  3087 0000345F E9A3FDFFFF          <1> 	jmp	error
  3088                              <1> sysfork_2: ; 1:
  3089 00003464 E897F0FFFF          <1> 	call	allocate_page
  3090                              <1> 	;jc	error
  3091                              <1> 	; 01/02/2022
  3092 00003469 72F4                <1> 	jc	short sysfork_err
  3093 0000346B 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3094                              <1> 	; Retro UNIX 386 v1 modification!
  3095 0000346C E888F2FFFF          <1> 	call	duplicate_page_dir
  3096                              <1> 		; EAX = New page directory 
  3097 00003471 7308                <1> 	jnc	short sysfork_3
  3098 00003473 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3099 00003474 E84FF2FFFF          <1> 	call 	deallocate_page
  3100                              <1> 	;jmp	error
  3101                              <1> 	; 01/02/2022
  3102 00003479 EBE4                <1> 	jmp	short sysfork_err
  3103                              <1> sysfork_3:
  3104                              <1> 	; Retro UNIX 386 v1 modification !
  3105 0000347B 56                  <1> 	push	esi
  3106 0000347C E8B3110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3107                              <1> 		      ; and interrupt return components (for IRET)
  3108 00003481 8705[63660000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3109 00003487 A3[67660000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3110 0000348C 5E                  <1> 	pop	esi
  3111 0000348D 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3112                              <1> 		; [u.usp] = esp
  3113 0000348E 89F7                <1> 	mov	edi, esi
  3114                              <1> 	;shl	di, 2
  3115                              <1> 	; 12/02/2022
  3116 00003490 C1E702              <1> 	shl	edi, 2
  3117 00003493 8987[90630000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3118 00003499 A3[5A660000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3119                              <1> 	; 28/08/2015
  3120 0000349E 0FB605[59660000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3121                              <1> 		; movb u.uno,-(sp) / save parent process number
  3122 000034A5 89C7                <1> 	mov	edi, eax
  3123 000034A7 50                  <1>         push	eax ; ** 
  3124 000034A8 8A87[63630000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3125                              <1> 	; 18/09/2015
  3126 000034AE 8886[63630000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3127                              <1> 	; 26/02/2022 (p.waitc is not used)
  3128                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3129                              <1> 	; 25/02/2022 (BugFix)
  3130                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3131                              <1> 	;			   ; ah - reset child's wait channel	
  3132 000034B4 89F0                <1> 	mov	eax, esi
  3133 000034B6 A2[59660000]        <1> 	mov	[u.uno], al ; child process number
  3134                              <1> 		;movb r1,u.uno / set child process number to r1
  3135 000034BB FE86[83630000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3136                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3137                              <1> 				  ; / process to active status
  3138                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3139                              <1> 			      ; / control tty buffer in r2
  3140                              <1>                 ; beq 2f / branch, if no such tty assigned
  3141                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3142                              <1> 	; 2:
  3143 000034C1 53                  <1> 	push	ebx  ; * return address for the child process
  3144                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3145                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3146                              <1> 		; mov $runq+4,r2
  3147 000034C2 E8C3110000          <1> 	call	putlu 
  3148                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3149                              <1> 			   ; / run queue
  3150                              <1> 	; 12/02/2022
  3151 000034C7 D1E6                <1> 	shl	esi, 1
  3152                              <1> 	;shl	si, 1
  3153                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3154                              <1> 		       ; / into p.pid table
  3155 000034C9 66FF05[FC650000]    <1> 	inc	word [mpid]
  3156                              <1> 		; inc mpid / increment m.pid; get a new process name
  3157 000034D0 66A1[FC650000]      <1> 	mov	ax, [mpid]
  3158 000034D6 668986[22630000]    <1> 	mov	[esi+p.pid-2], ax
  3159                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3160                              <1> 				    ; / in child process' name slot
  3161 000034DD 5A                  <1> 	pop	edx  ; * return address for the child process
  3162                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3163 000034DE 5B                  <1>   	pop	ebx  ; **
  3164                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3165                              <1> 		; movb (sp),r2 / put parent process number in r2
  3166                              <1> 	; 01/02/2022
  3167 000034DF D0E3                <1> 	shl	bl, 1
  3168                              <1> 	;shl 	bx, 1
  3169                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3170                              <1> 	; ebx <= 32
  3171                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3172 000034E1 668B83[22630000]    <1> 	mov	ax, [ebx+p.pid-2]
  3173                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3174                              <1> 				   ; / process
  3175 000034E8 668986[42630000]    <1> 	mov	[esi+p.ppid-2], ax
  3176                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3177                              <1> 			  ; / in parent process slot for child
  3178 000034EF A3[10660000]        <1> 	mov	[u.r0], eax	
  3179                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3180                              <1> 			     ; / at location where r0 was saved
  3181 000034F4 8B2D[08660000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3182 000034FA 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3183                              <1> 			   ; * return address for the child process
  3184                              <1> 		; mov $sysret1,-(sp) /
  3185                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3186                              <1> 			      ; / user is swapped out
  3187                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3188                              <1> 	; 04/09/2015 - 01/09/2015
  3189                              <1> 	; [u.usp] = esp
  3190 000034FD 68[27320000]        <1> 	push	sysret ; ***
  3191 00003502 8925[0C660000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3192                              <1> 			     ; (for child process)	
  3193 00003508 31C0                <1> 	xor 	eax, eax
  3194 0000350A 66A3[40660000]      <1> 	mov 	[u.ttyp], ax ; 0
  3195                              <1> 	;
  3196 00003510 E81F110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3197                              <1> 		;jsr r0,wswap / put child process out on drum
  3198                              <1> 		;jsr r0,unpack / unpack user stack
  3199                              <1> 		;mov u.usp,sp / restore user stack pointer
  3200                              <1> 		; tst (sp)+ / bump stack pointer
  3201                              <1> 	; Retro UNIX 386 v1 modification !
  3202 00003515 58                  <1> 	pop	eax ; ***
  3203                              <1> 	;shl	bx, 1
  3204                              <1> 	; 01/02/2022
  3205 00003516 D0E3                <1> 	shl	bl, 1 
  3206                              <1> 		; ebx <= 64
  3207 00003518 8B83[90630000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3208 0000351E E83A110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3209                              <1> 		      ; registers and return address (for IRET)
  3210                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3211 00003523 0FB705[FC650000]    <1>         movzx   eax, word [mpid]
  3212 0000352A A3[10660000]        <1> 	mov	[u.r0], eax
  3213                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3214                              <1> 			       ; / where r0 was saved
  3215                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3216                              <1> 			       ; / process return
  3217                              <1> 	;xor	ebx, ebx
  3218 0000352F 31F6                <1> 	xor     esi, esi
  3219                              <1> 		;clr r1
  3220                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3221                              <1> 	      ; / opened by the parent process
  3222                              <1> 	; 01/09/2015
  3223                              <1> 	;xor	bh, bh
  3224                              <1> 	;mov 	bl, [esi+u.fp]
  3225 00003531 8A86[16660000]      <1> 	mov 	al, [esi+u.fp]
  3226                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3227                              <1>         ;or	bl, bl
  3228 00003537 08C0                <1> 	or	al, al
  3229 00003539 740C                <1> 	jz	short sysfork_5	
  3230                              <1> 		; beq 2f / file has not been opened by parent, 
  3231                              <1> 		       ; / so branch
  3232 0000353B B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3233 0000353D F6E4                <1> 	mul	ah
  3234                              <1> 	;;movzx	ebx, ax
  3235                              <1> 	;mov	bx, ax
  3236 0000353F 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3237                              <1> 	;shl	bx, 3
  3238                              <1> 		; asl r2 / multiply by 8
  3239                              <1>        		; asl r2 / to get index into fsp table
  3240                              <1>        		; asl r2
  3241 00003541 FE83[D2630000]      <1>   	inc     byte [ebx+fsp-2]
  3242                              <1> 		; incb fsp-2(r2) / increment number of processes
  3243                              <1> 			     ; / using file, because child will now be
  3244                              <1> 			     ; / using this file
  3245                              <1> sysfork_5: ; 2:
  3246 00003547 46                  <1>         inc     esi
  3247                              <1> 		; inc r1 / get next open file
  3248 00003548 6683FE0A            <1>         cmp     si, 10
  3249                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3250                              <1> 			    ; / can be opened
  3251 0000354C 72E3                <1> 	jb	short sysfork_4	
  3252                              <1> 		; blt 1b / check next entry
  3253 0000354E E9D4FCFFFF          <1> 	jmp	sysret
  3254                              <1> 		; br sysret1
  3255                              <1> 
  3256                              <1> sysread: ; < read from file >
  3257                              <1> 	; 27/02/2022
  3258                              <1> 	; 01/02/2022
  3259                              <1> 	; 13/05/2015
  3260                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3261                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3262                              <1> 	;
  3263                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3264                              <1> 	; characters to be read. If finds the file from the file
  3265                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3266                              <1> 	; is returned from a successful open call (sysopen).
  3267                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3268                              <1> 	; is read into core via 'readi'.
  3269                              <1> 	;
  3270                              <1> 	; Calling sequence:
  3271                              <1> 	;	sysread; buffer; nchars
  3272                              <1> 	; Arguments:
  3273                              <1> 	;	buffer - location of contiguous bytes where 
  3274                              <1> 	;		 input will be placed.
  3275                              <1> 	;	nchars - number of bytes or characters to be read.
  3276                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3277                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3278                              <1> 	; ...............................................................
  3279                              <1> 	;				
  3280                              <1> 	; Retro UNIX 8086 v1 modification: 
  3281                              <1> 	;       'sysread' system call has three arguments; so,
  3282                              <1> 	;	* 1st argument, file descriptor is in BX register
  3283                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3284                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3285                              <1> 	;
  3286                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3287                              <1> 	;	to the user with number of bytes read. 
  3288                              <1> 	;
  3289 00003553 E840000000          <1> 	call	rw1
  3290                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3291                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3292                              <1>        	; 27/02/2022
  3293 00003558 7239                <1> 	jc	short sysread_err
  3294 0000355A F6C480              <1> 	test	ah, 80h
  3295                              <1> 		; tst r1 / negative i-number?
  3296                              <1> 	;jnz	error
  3297                              <1> 		; ble error1 / yes, error 1 to read
  3298                              <1> 			   ; / it should be positive
  3299                              <1> 	; 01/02/2022
  3300                              <1> 	;jnz	short rw_error
  3301                              <1> 	;27/02/2022
  3302 0000355D 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3303                              <1> 	;
  3304 0000355F E88D150000          <1> 	call	readi
  3305                              <1> 		; jsr r0,readi / read data into core
  3306 00003564 EB14                <1> 	jmp	short rw0
  3307                              <1> 		; br 1f
  3308                              <1> 
  3309                              <1> syswrite: ; < write to file >
  3310                              <1> 	; 27/02/2022
  3311                              <1> 	; 01/02/2022
  3312                              <1> 	; 13/05/2015
  3313                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3314                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3315                              <1> 	;
  3316                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3317                              <1> 	; and the number of characters to write. If finds the file
  3318                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3319                              <1> 	; descriptor is returned from a successful open or create call
  3320                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3321                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3322                              <1> 	;
  3323                              <1> 	; Calling sequence:
  3324                              <1> 	;	syswrite; buffer; nchars
  3325                              <1> 	; Arguments:
  3326                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3327                              <1> 	;	nchars - number of characters to be written.
  3328                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3329                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3330                              <1> 	; ...............................................................
  3331                              <1> 	;				
  3332                              <1> 	; Retro UNIX 8086 v1 modification: 
  3333                              <1> 	;       'syswrite' system call has three arguments; so,
  3334                              <1> 	;	* 1st argument, file descriptor is in BX register
  3335                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3336                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3337                              <1> 	;
  3338                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3339                              <1> 	;	to the user with number of bytes written. 
  3340                              <1> 	;
  3341 00003566 E82D000000          <1> 	call	rw1
  3342                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3343                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3344                              <1> 	; 01/02/2022
  3345                              <1> 	;jnc	short syswrite_1
  3346                              <1> ;rw_error:
  3347                              <1> 	;jmp	error
  3348                              <1> 	; 27/02/2022
  3349 0000356B 7226                <1> 	jc	short short syswrite_err
  3350                              <1> syswrite_1:
  3351 0000356D F6C480              <1>         test	ah, 80h
  3352                              <1> 		; tst r1 / positive i-number ?
  3353 00003570 7417                <1>         jz	short rw3 ; 13/05/2015
  3354                              <1> 	;jz	error
  3355                              <1> 		; bge error1 / yes, error 1 
  3356                              <1> 			   ; / negative i-number means write
  3357 00003572 66F7D8              <1> 	neg	ax
  3358                              <1> 		; neg r1 / make it positive
  3359 00003575 E865170000          <1> 	call	writei
  3360                              <1>         	; jsr r0,writei / write data
  3361                              <1> rw0: ; 1:
  3362 0000357A A1[38660000]        <1>         mov	eax, [u.nread]
  3363 0000357F A3[10660000]        <1> 	mov	[u.r0], eax
  3364                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3365                              <1> 				  ; / into (u.r0)
  3366 00003584 E99EFCFFFF          <1> 	jmp	sysret
  3367                              <1>         	; br sysret1
  3368                              <1> rw3: 
  3369                              <1> 	; 13/05/2015
  3370 00003589 C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3370 00003591 0000                <1>
  3371                              <1> 	;stc
  3372                              <1> 	;retn
  3373                              <1> 	; 27/02/2022 (BugFix)
  3374                              <1> sysread_err:
  3375                              <1> syswrite_err:
  3376 00003593 E96FFCFFFF          <1> 	jmp	error
  3377                              <1> 
  3378                              <1> rw1:	
  3379                              <1> 	; 14/05/2015
  3380                              <1> 	; 13/05/2015
  3381                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3382                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3383                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3384                              <1> 	;
  3385                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3386                              <1> 				;(in the user's virtual memory space)
  3387                              <1> 	;mov	[u.count], edx 
  3388                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3389                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3390                              <1> 	;;mov	eax, ebx ; file descriptor
  3391                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3392                              <1> 		             ; / (index to u.fp table) in r1
  3393                              <1> 	; 13/05/2015
  3394 00003598 C705[10660000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3394 000035A0 0000                <1>
  3395                              <1> 	;
  3396                              <1> 	;; call	getf
  3397                              <1>         ; eBX = File descriptor
  3398 000035A2 E82E0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3399                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3400                              <1> 	; AX = I-number of the file ; negative i-number means write
  3401                              <1> 	; 13/05/2015
  3402 000035A7 6683F801            <1> 	cmp 	ax, 1
  3403 000035AB 7217                <1> 	jb	short rw2
  3404                              <1> 	;
  3405 000035AD 890D[30660000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3406                              <1> 				;(in the user's virtual memory space)
  3407 000035B3 8915[34660000]      <1> 	mov	[u.count], edx 
  3408                              <1> 	; 14/05/2015
  3409 000035B9 C705[5F660000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3409 000035C1 0000                <1>
  3410 000035C3 C3                  <1> 	retn
  3411                              <1>         	; rts r0
  3412                              <1> rw2:
  3413                              <1> 	; 13/05/2015
  3414 000035C4 C705[5F660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3414 000035CC 0000                <1>
  3415 000035CE C3                  <1> 	retn
  3416                              <1> 
  3417                              <1> sysopen: ;<open file>
  3418                              <1> 	; 12/02/2022
  3419                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3420                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3421                              <1> 	;
  3422                              <1> 	; 'sysopen' opens a file in following manner:
  3423                              <1> 	;    1) The second argument in a sysopen says whether to
  3424                              <1> 	;	open the file ro read (0) or write (>0).
  3425                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3426                              <1> 	;    3) The file is opened by 'iopen'.
  3427                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3428                              <1> 	;	and the user's open file list - u.fp.
  3429                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3430                              <1> 	;	b) An entry for the file is created in the fsp table.
  3431                              <1> 	;	c) The number of this entry is put on u.fp list.
  3432                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3433                              <1> 	;	   to by u.r0.
  3434                              <1> 	;
  3435                              <1> 	; Calling sequence:
  3436                              <1> 	;	sysopen; name; mode
  3437                              <1> 	; Arguments:
  3438                              <1> 	;	name - file name or path name
  3439                              <1> 	;	mode - 0 to open for reading
  3440                              <1> 	;	       1 to open for writing
  3441                              <1> 	; Inputs: (arguments)
  3442                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3443                              <1> 	;		  is put into r0's location on the stack.	
  3444                              <1> 	; ...............................................................
  3445                              <1> 	;				
  3446                              <1> 	; Retro UNIX 8086 v1 modification: 
  3447                              <1> 	;       'sysopen' system call has two arguments; so,
  3448                              <1> 	;	* 1st argument, name is pointed to by BX register
  3449                              <1> 	;	* 2nd argument, mode is in CX register
  3450                              <1> 	;
  3451                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3452                              <1> 	;	to the user with the file descriptor/number 
  3453                              <1> 	;	(index to u.fp list).
  3454                              <1> 	;
  3455                              <1> 	;call	arg2
  3456                              <1> 	; * name - 'u.namep' points to address of file/path name
  3457                              <1> 	;          in the user's program segment ('u.segmnt')
  3458                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3459                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3460                              <1> 	;          which is on top of stack.
  3461                              <1> 	;
  3462                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3463                              <1> 	;
  3464                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3465                              <1> 
  3466 000035CF 891D[28660000]      <1> 	mov	[u.namep], ebx
  3467                              <1> 	;push	cx
  3468 000035D5 51                  <1> 	push	ecx ; 12/02/2022
  3469 000035D6 E82D0B0000          <1> 	call	namei
  3470                              <1> 		; jsr r0,namei / i-number of file in r1
  3471                              <1>      	;and	ax, ax
  3472                              <1> 	;jz	error ; File not found
  3473 000035DB 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3474                              <1> 	;jc	error ; 27/05/2013
  3475                              <1> 		; br  error2 / file not found
  3476                              <1>    	;pop	dx ; mode
  3477                              <1> 	;push	dx
  3478                              <1> 	; 12/02/2022
  3479                              <1> 	;pop	edx ; * ; mode
  3480                              <1> 	;push	edx ; *
  3481 000035DD 8B1424              <1> 	mov	edx, [esp] ; *
  3482                              <1> 	; edx = open mode (0 or 1)
  3483                              <1> 	;or	dx, dx
  3484 000035E0 08D2                <1> 	or	dl, dl
  3485                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3486                              <1> 		         ; / 0 means, open for read)
  3487 000035E2 7403                <1> 	jz	short sysopen_0
  3488                              <1> 		; beq 1f / yes, leave i-number positive
  3489                              <1> syscreat_0: 
  3490                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3491 000035E4 66F7D8              <1> 	neg	ax
  3492                              <1>         	; neg r1 / open for writing so make i-number negative
  3493                              <1> sysopen_0: ;1:
  3494 000035E7 E88B1B0000          <1> 	call	iopen
  3495                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3496 000035EC 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3497                              <1> 	;and	dx, dx
  3498 000035ED 20D2                <1> 	and	dl, dl
  3499                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3500 000035EF 7403                <1> 	jz	short sysopen_2
  3501                              <1>         	; beq op1 / is open for read op1
  3502                              <1> sysopen_1: ;op0:
  3503 000035F1 66F7D8              <1> 	neg	ax
  3504                              <1>         	; neg r1 
  3505                              <1> 		     ;/ make i-number positive if open for writing [???]
  3506                              <1> 	;; NOTE: iopen always make i-number positive.
  3507                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3508                              <1> sysopen_2: ;op1:
  3509 000035F4 31F6                <1>         xor     esi, esi
  3510                              <1>         	; clr r2 / clear registers
  3511 000035F6 31DB                <1>         xor     ebx, ebx
  3512                              <1> 		; clr r3
  3513                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3514 000035F8 389E[16660000]      <1>         cmp     [esi+u.fp], bl ; 0
  3515                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3516 000035FE 7625                <1>         jna	short sysopen_4
  3517                              <1> 		; beq 1f / if byte in list is 0 branch
  3518 00003600 46                  <1>         inc     esi
  3519                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3520 00003601 6683FE0A            <1>         cmp     si, 10
  3521                              <1> 		; cmp r2,$10. / reached end of list?
  3522 00003605 72F1                <1> 	jb	short sysopen_3
  3523                              <1> 		; blt 1b / no, go back
  3524                              <1> toomanyf:
  3525                              <1> 	; 14/05/2015
  3526 00003607 C705[5F660000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3526 0000360F 0000                <1>
  3527 00003611 E9F1FBFFFF          <1> 	jmp	error
  3528                              <1>         	; br error2 / yes, error (no files open)
  3529                              <1> fnotfound: 
  3530                              <1> 	; 14/05/2015
  3531 00003616 C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3531 0000361E 0000                <1>
  3532 00003620 E9E2FBFFFF          <1> 	jmp	error
  3533                              <1> 
  3534                              <1> sysopen_4: ; 1:
  3535 00003625 6683BB[D4630000]00  <1>         cmp     word [ebx+fsp], 0
  3536                              <1> 		; tst fsp(r3) / scan fsp entries
  3537 0000362D 7610                <1>         jna     short sysopen_5
  3538                              <1> 		; beq 1f / if 0 branch
  3539                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3540 0000362F 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3541                              <1> 		; add $8.,r3 / add 8 to r3 
  3542                              <1> 			; / to bump it to next entry mfsp table
  3543 00003633 6681FBF401          <1>         cmp     bx, nfiles*10
  3544                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3545 00003638 72EB                <1> 	jb	short sysopen_4
  3546                              <1>        		; blt 1b / no, back
  3547 0000363A E9C8FBFFFF          <1> 	jmp	error
  3548                              <1>         	; br error2 / yes, error
  3549                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3550 0000363F 668983[D4630000]    <1>         mov     [ebx+fsp], ax
  3551                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3552                              <1> 			; / into next available entry in fsp table,
  3553                              <1> 	; 12/02/2022
  3554                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3555                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3556                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3557                              <1> 	;xor	edi, edi
  3558                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3559                              <1> 	;	; clr fsp+4(r3)
  3560                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3561                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3562 00003646 31C0                <1> 	xor	eax, eax
  3563 00003648 8983[D8630000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3564 0000364E 668983[DC630000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3565                              <1> 
  3566 00003655 66A1[F4650000]      <1> 	mov	ax, [cdev]
  3567 0000365B 668983[D6630000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3568                              <1> 
  3569 00003662 89D8                <1>   	mov	eax, ebx
  3570 00003664 B30A                <1> 	mov	bl, 10
  3571 00003666 F6F3                <1> 	div	bl 
  3572                              <1> 		; asr r3
  3573                              <1> 		; asr r3 / divide by 8 
  3574                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3575 00003668 FEC0                <1> 	inc	al
  3576                              <1>         	; inc r3 / add 1 to get fsp entry number
  3577 0000366A 8886[16660000]      <1>         mov     [esi+u.fp], al
  3578                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3579                              <1> 			; / next available slot in u.fp list
  3580 00003670 8935[10660000]      <1>         mov     [u.r0], esi
  3581                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3582                              <1> 			     ; / into r0 loc on stack
  3583 00003676 E9ACFBFFFF          <1>         jmp	sysret
  3584                              <1> 		; br sysret2
  3585                              <1> 
  3586                              <1> 	;
  3587                              <1> 	; 'fsp' table (10 bytes/entry)
  3588                              <1> 	; bit 15				   bit 0
  3589                              <1> 	; ---|-------------------------------------------
  3590                              <1> 	; r/w|		i-number of open file
  3591                              <1> 	; ---|-------------------------------------------
  3592                              <1> 	;		   device number
  3593                              <1> 	; -----------------------------------------------
  3594                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3595                              <1> 	; -----------------------------------------------
  3596                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3597                              <1> 	; ----------------------|------------------------
  3598                              <1> 	;  flag that says file 	| number of processes
  3599                              <1> 	;   has been deleted	| that have file open 
  3600                              <1> 	; ----------------------|------------------------
  3601                              <1> 	;
  3602                              <1> 
  3603                              <1> syscreat: ; < create file >
  3604                              <1> 	; 12/02/2022
  3605                              <1> 	; 01/02/2022
  3606                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3607                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3608                              <1> 	;
  3609                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3610                              <1> 	; u.namep points to name of the file and mode is put
  3611                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3612                              <1> 	; If the file aready exists, it's mode and owner remain 
  3613                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3614                              <1> 	; did not exist, an i-node is created with the new mode via
  3615                              <1> 	; 'maknod' whether or not the file already existed, it is
  3616                              <1> 	; open for writing. The fsp table is then searched for a free
  3617                              <1> 	; entry. When a free entry is found, proper data is placed
  3618                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3619                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3620                              <1> 	; is put in the user's r0. 			
  3621                              <1> 	;
  3622                              <1> 	; Calling sequence:
  3623                              <1> 	;	syscreate; name; mode
  3624                              <1> 	; Arguments:
  3625                              <1> 	;	name - name of the file to be created
  3626                              <1> 	;	mode - mode of the file to be created
  3627                              <1> 	; Inputs: (arguments)
  3628                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3629                              <1> 	;		   (the file descriptor of new file)
  3630                              <1> 	; ...............................................................
  3631                              <1> 	;				
  3632                              <1> 	; Retro UNIX 8086 v1 modification: 
  3633                              <1> 	;       'syscreate' system call has two arguments; so,
  3634                              <1> 	;	* 1st argument, name is pointed to by BX register
  3635                              <1> 	;	* 2nd argument, mode is in CX register
  3636                              <1> 	;
  3637                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3638                              <1> 	;	to the user with the file descriptor/number 
  3639                              <1> 	;	(index to u.fp list).
  3640                              <1> 	;
  3641                              <1> 	;call	arg2
  3642                              <1> 	; * name - 'u.namep' points to address of file/path name
  3643                              <1> 	;          in the user's program segment ('u.segmnt')
  3644                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3645                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3646                              <1> 	;          which is on top of stack.
  3647                              <1> 	;
  3648                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3649                              <1> 			    ; / on stack
  3650 0000367B 891D[28660000]      <1> 	mov	[u.namep], ebx ; file name address
  3651                              <1> 	;push	cx ; mode
  3652                              <1> 	; 01/02/2022
  3653 00003681 51                  <1> 	push	ecx ; mode
  3654 00003682 E8810A0000          <1> 	call 	namei        	
  3655                              <1> 		; jsr r0,namei / get the i-number
  3656                              <1>         ;and	ax, ax
  3657                              <1> 	;jz	short syscreat_2	       	
  3658 00003687 721B                <1> 	jc	short syscreat_2
  3659                              <1> 		; br  2f / if file doesn't exist 2f
  3660                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3661                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3662 00003689 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3663                              <1>         ;jb	syscreat_0 ; yes
  3664                              <1> 	; 02/02/2022
  3665 0000368D 7305                <1> 	jnb	short syscreat_1
  3666 0000368F E950FFFFFF          <1> 	jmp	syscreat_0
  3667                              <1> syscreat_1:
  3668 00003694 66F7D8              <1> 	neg 	ax
  3669                              <1>         	; neg r1 / if file already exists make i-number 
  3670                              <1> 		       ; / negative (open for writing)
  3671 00003697 E8DB1A0000          <1> 	call	iopen
  3672                              <1>         	; jsr r0,iopen /
  3673 0000369C E8A8130000          <1> 	call	itrunc
  3674                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3675                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3676                              <1> 	; 01/02/2022
  3677 000036A1 59                  <1> 	pop	ecx ; mode
  3678                              <1> 	; 12/02/2022
  3679 000036A2 EB0E                <1> 	jmp	short syscreat_3
  3680                              <1>         ;jmp	sysopen_1
  3681                              <1>         	; br op0
  3682                              <1> syscreat_2: ; 2: / file doesn't exist
  3683                              <1> 	; 01/02/2022
  3684 000036A4 58                  <1> 	pop	eax ; mode
  3685                              <1> 	;pop	ax
  3686                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3687 000036A5 30E4                <1> 	xor	ah, ah	
  3688                              <1>         	; bic $!377,r1 / clear upper byte
  3689 000036A7 E86D0D0000          <1> 	call 	maknod
  3690                              <1>         	; jsr r0,maknod / make an i-node for this file
  3691 000036AC 66A1[42660000]      <1> 	mov	ax, [u.dirbuf]
  3692                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3693                              <1> 			        ; / for this new file in r1
  3694                              <1> syscreat_3:
  3695 000036B2 E93AFFFFFF          <1>         jmp     sysopen_1
  3696                              <1>         	; br op0 / open the file
  3697                              <1> 
  3698                              <1> sysmkdir: ; < make directory >
  3699                              <1> 	; 01/02/2022
  3700                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3701                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3702                              <1> 	;
  3703                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3704                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3705                              <1> 	; The special entries '.' and '..' are not present.
  3706                              <1> 	; Errors are indicated if the directory already exists or		
  3707                              <1> 	; user is not the super user. 
  3708                              <1> 	;
  3709                              <1> 	; Calling sequence:
  3710                              <1> 	;	sysmkdir; name; mode
  3711                              <1> 	; Arguments:
  3712                              <1> 	;	name - points to the name of the directory
  3713                              <1> 	;	mode - mode of the directory
  3714                              <1> 	; Inputs: (arguments)
  3715                              <1> 	; Outputs: -
  3716                              <1> 	;    (sets 'directory' flag to 1; 
  3717                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3718                              <1> 	; ...............................................................
  3719                              <1> 	;				
  3720                              <1> 	; Retro UNIX 8086 v1 modification: 
  3721                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3722                              <1> 	;	* 1st argument, name is pointed to by BX register
  3723                              <1> 	;	* 2nd argument, mode is in CX register
  3724                              <1> 		
  3725                              <1> ; / make a directory
  3726                              <1> 	
  3727                              <1> 	;call	arg2
  3728                              <1> 	; * name - 'u.namep' points to address of file/path name
  3729                              <1> 	;          in the user's program segment ('u.segmnt')
  3730                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3731                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3732                              <1> 	;          which is on top of stack.
  3733                              <1> 
  3734                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3735                              <1> 			    ; / on stack
  3736 000036B7 891D[28660000]      <1> 	mov	[u.namep], ebx
  3737                              <1> 	;push	cx ; mode
  3738                              <1> 	; 01/02/2022
  3739 000036BD 51                  <1> 	push	ecx ; mode
  3740 000036BE E8450A0000          <1> 	call	namei
  3741                              <1>         	; jsr r0,namei / get the i-number
  3742                              <1>         	;     br .+4 / if file not found branch around error
  3743                              <1>         ;xor 	ax, ax
  3744                              <1> 	;jnz	error
  3745 000036C3 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3746                              <1> 	;jnc	error	
  3747                              <1> 		; br  error2 / directory already exists (error)
  3748 000036C5 803D[56660000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3749                              <1>         	;tstb u.uid / is user the super user
  3750                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3751                              <1> 	;;jna	error
  3752                              <1> 	; 01/02/2022 (BugFix)
  3753 000036CC 7721                <1> 	ja	short dir_access_err
  3754                              <1>         	;bne error2 / no, not allowed
  3755                              <1> 	;pop	ax
  3756                              <1> 	; 01/02/2022
  3757 000036CE 58                  <1> 	pop	eax ; mode
  3758                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3759 000036CF 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3760                              <1>         	;bic $!317,r1 / all but su and ex
  3761                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3762 000036D3 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3763                              <1>         	;bis $40000,r1 / directory flag
  3764 000036D6 E83E0D0000          <1> 	call	maknod
  3765                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3766                              <1> sysclose_sysret: ; 01/02/2022
  3767 000036DB E947FBFFFF          <1> 	jmp	sysret
  3768                              <1>         	;br sysret2 /
  3769                              <1> dir_exists:
  3770                              <1> 	; 14/05/2015
  3771 000036E0 C705[5F660000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3771 000036E8 0000                <1>
  3772 000036EA E918FBFFFF          <1> 	jmp	error
  3773                              <1> dir_access_err:
  3774                              <1> 	; 14/05/2015
  3775 000036EF C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3775 000036F7 0000                <1>
  3776 000036F9 E909FBFFFF          <1> 	jmp	error
  3777                              <1> 
  3778                              <1> sysclose: ;<close file>
  3779                              <1> 	; 01/02/2022
  3780                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3781                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3782                              <1> 	;
  3783                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3784                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3785                              <1> 	; is put in r1 and 'fclose' is called.
  3786                              <1> 	;
  3787                              <1> 	; Calling sequence:
  3788                              <1> 	;	sysclose
  3789                              <1> 	; Arguments:
  3790                              <1> 	;	-  
  3791                              <1> 	; Inputs: *u.r0 - file descriptor
  3792                              <1> 	; Outputs: -
  3793                              <1> 	; ...............................................................
  3794                              <1> 	;				
  3795                              <1> 	; Retro UNIX 8086 v1 modification:
  3796                              <1> 	;	 The user/application program puts file descriptor
  3797                              <1> 	;        in BX register as 'sysclose' system call argument.
  3798                              <1> 	; 	 (argument transfer method 1)
  3799                              <1> 
  3800                              <1> 	; / close the file
  3801                              <1> 	
  3802 000036FE 89D8                <1> 	mov 	eax, ebx
  3803 00003700 E88D090000          <1> 	call 	fclose
  3804                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3805                              <1> 		; jsr r0,fclose / close the file
  3806                              <1>                	; br error2 / unknown file descriptor
  3807                              <1> 		; br sysret2
  3808                              <1> 	; 14/05/2015
  3809                              <1> 	;jnc	sysret
  3810                              <1> 	; 01/02/2022
  3811 00003705 73D4                <1> 	jnc	short sysclose_sysret
  3812 00003707 C705[5F660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3812 0000370F 0000                <1>
  3813 00003711 E9F1FAFFFF          <1> 	jmp	error
  3814                              <1> 
  3815                              <1> sysemt:
  3816                              <1> 	; 23/02/2022
  3817                              <1> 	; 01/02/2022
  3818                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3819                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3820                              <1> 	;
  3821                              <1> 	; Retro UNIX 8086 v1 modification: 
  3822                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3823                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3824                              <1> 	;
  3825                              <1> 	; Retro UNIX 8086 v1 feature only!
  3826                              <1> 	;	Using purpose: Kernel will start without time-out
  3827                              <1> 	;	(internal clock/timer) functionality.
  3828                              <1> 	;	Then etc/init will enable clock/timer for
  3829                              <1> 	;	multi tasking. (Then it will not be disabled again
  3830                              <1> 	;	except hardware reset/restart.)
  3831                              <1> 
  3832 00003716 803D[56660000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3833                              <1> 	;;ja	error
  3834                              <1> 	;ja	badsys ; 14/05/2015
  3835                              <1> 	; 01/02/2022
  3836                              <1> 	;jna	short emt_0
  3837                              <1> 	;jmp	badsys
  3838 0000371D 773A                <1> 	ja	short sysilgins ; jmp badsys
  3839                              <1> emt_0:
  3840 0000371F FA                  <1> 	cli
  3841 00003720 21DB                <1> 	and	ebx, ebx
  3842 00003722 7429                <1> 	jz	short emt_2
  3843                              <1> 	; Enable multi tasking -time sharing-
  3844 00003724 B8[D2460000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3845                              <1> 	; 23/02/2022
  3846 00003729 BA[440A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3847                              <1> emt_1:
  3848 0000372E A3[0A070000]        <1> 	mov	[x_timer], eax
  3849                              <1> 	; 23/02/2022 (Temporary)
  3850 00003733 8915[0E070000]      <1> 	mov	[x_rtci], edx
  3851 00003739 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3852 0000373B E853020000          <1> 	call	wttyc  ; clear video page
  3853 00003740 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3854 00003742 E84C020000          <1> 	call	wttyc  ; clear video page
  3855                              <1> 	;
  3856 00003747 FB                  <1> 	sti
  3857 00003748 E9DAFAFFFF          <1> 	jmp	sysret
  3858                              <1> emt_2:
  3859                              <1> 	; Disable multi tasking -time sharing-
  3860 0000374D B8[16070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3861                              <1> 	; 23/02/2022
  3862 00003752 BA[4B0A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3863                              <1> 	;
  3864 00003757 EBD5                <1> 	jmp	short emt_1
  3865                              <1> 
  3866                              <1> 	; Original UNIX v1 'sysemt' routine
  3867                              <1> ;sysemt:
  3868                              <1>         ;
  3869                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3870                              <1> 			 ; / in loc 30
  3871                              <1>         ;cmp    30,$core / was the argument a lower address 
  3872                              <1> 			; / than core
  3873                              <1>         ;blo    1f / yes, rtssym
  3874                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3875                              <1> 			; / and less than "ecore"
  3876                              <1>         ;blo    2f / yes, sysret2
  3877                              <1> ;1:
  3878                              <1>         ;mov    $rtssym,30
  3879                              <1> ;2:
  3880                              <1>         ;br     sysret2
  3881                              <1> 
  3882                              <1> 	; 01/02/2022
  3883                              <1> sysilgins:
  3884                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3885                              <1> 	; 03/06/2013
  3886                              <1> 	; Retro UNIX 8086 v1 modification: 
  3887                              <1> 	;	not a valid system call ! (not in use)
  3888                              <1> 	;
  3889 00003759 E952FBFFFF          <1> 	jmp	badsys
  3890                              <1> 	;jmp	error
  3891                              <1> 	;;jmp 	sysret
  3892                              <1> 
  3893                              <1> 	; Original UNIX v1 'sysemt' routine
  3894                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3895                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3896                              <1> 			  ;/ put it in loc 8.,
  3897                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3898                              <1> 		       ; / trap address
  3899                              <1>         ;blo    1f / is the address a user core address?  
  3900                              <1> 		; / yes, go to 2f
  3901                              <1>         ;cmp    10,$ecore
  3902                              <1>         ;blo    2f
  3903                              <1> ;1:
  3904                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3905                              <1> 		    ; / instruction trap address for the system
  3906                              <1> ;2:
  3907                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3908                              <1> 
  3909                              <1> sysmdate: ; < change the modification time of a file >
  3910                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3911                              <1> 	;	(ECX input)
  3912                              <1> 	; 01/02/2022
  3913                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3914                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3915                              <1> 	;
  3916                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3917                              <1> 	; file into core. The user is checked if he is the owner 
  3918                              <1> 	; or super user. If he is neither an error occurs.
  3919                              <1> 	; 'setimod' is then called to set the i-node modification
  3920                              <1> 	; byte and the modification time, but the modification time
  3921                              <1> 	; is overwritten by whatever get put on the stack during
  3922                              <1> 	; a 'systime' system call. This calls are restricted to
  3923                              <1> 	; the super user.		
  3924                              <1> 	;
  3925                              <1> 	; Calling sequence:
  3926                              <1> 	;	sysmdate; name
  3927                              <1> 	; Arguments:
  3928                              <1> 	;	name - points to the name of file
  3929                              <1> 	; Inputs: (arguments)
  3930                              <1> 	; Outputs: -
  3931                              <1> 	; ...............................................................
  3932                              <1> 	;				
  3933                              <1> 	; Retro UNIX 8086 v1 modification: 
  3934                              <1> 	;	 The user/application program puts address 
  3935                              <1> 	;	 of the file name in BX register 
  3936                              <1> 	;	 as 'sysmdate' system call argument.
  3937                              <1> 	;
  3938                              <1> ; / change the modification time of a file
  3939                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3940 0000375E 891D[28660000]      <1>         mov	[u.namep], ebx
  3941                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3942 00003764 890D[90620000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3943 0000376A E899090000          <1> 	call	namei
  3944                              <1> 		; jsr r0,namei / get its i-number
  3945                              <1> 	;;jc	error       
  3946                              <1> 		; br error2 / no, such file
  3947                              <1> 	;jc	fnotfound ; file not found !
  3948                              <1> 	; 01/02/2022
  3949 0000376F 7305                <1> 	jnc	short mdate_0
  3950 00003771 E9A0FEFFFF          <1> 	jmp	fnotfound
  3951                              <1> mdate_0:
  3952 00003776 E8A2110000          <1> 	call	iget
  3953                              <1> 		; jsr r0,iget / get i-node into core
  3954 0000377B A0[56660000]        <1> 	mov	al, [u.uid]
  3955 00003780 3A05[07630000]      <1> 	cmp	al, [i.uid]
  3956                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3957 00003786 7413                <1> 	je	short mdate_1
  3958                              <1>         	; beq 1f / yes
  3959 00003788 20C0                <1> 	and	al, al
  3960                              <1> 		; tstb u.uid / no, is user the super user
  3961                              <1> 	;jnz	error
  3962                              <1> 		; bne error2 / no, error
  3963 0000378A 740F                <1> 	jz	short mdate_1
  3964 0000378C C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3964 00003794 0000                <1>
  3965                              <1> sysstty_err:	; 01/02/2022
  3966 00003796 E96CFAFFFF          <1> 	jmp	error
  3967                              <1> mdate_1: ;1:
  3968 0000379B E887120000          <1> 	call	setimod
  3969                              <1>         	; jsr r0,setimod / fill in modification data,
  3970                              <1> 		               ; / time etc.
  3971 000037A0 BE[90620000]        <1> 	mov	esi, p_time
  3972 000037A5 BF[1E630000]        <1> 	mov	edi, i.mtim
  3973 000037AA A5                  <1> 	movsd
  3974                              <1> 		; mov 4(sp),i.mtim / move present time to
  3975                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3976 000037AB E977FAFFFF          <1>         jmp	sysret
  3977                              <1> 		; br sysret2
  3978                              <1> 
  3979                              <1> 	; 01/02/2022
  3980                              <1> sysstty_err_s:
  3981 000037B0 880D[10660000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3982 000037B6 EBDE                <1> 	jmp	short sysstty_err
  3983                              <1> 
  3984                              <1> sysstty: ; < set tty status and mode >
  3985                              <1> 	; 23/02/2022
  3986                              <1> 	; 22/02/2022
  3987                              <1> 	; 02/02/2022
  3988                              <1> 	; 01/02/2022 (clear screen)
  3989                              <1> 	; 17/11/2015
  3990                              <1> 	; 12/11/2015
  3991                              <1> 	; 29/10/2015
  3992                              <1> 	; 17/10/2015
  3993                              <1> 	; 13/10/2015
  3994                              <1> 	; 29/06/2015
  3995                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3996                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3997                              <1> 	;
  3998                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3999                              <1> 	; whose file descriptor is in (u.r0).
  4000                              <1> 	;
  4001                              <1> 	; Calling sequence:
  4002                              <1> 	;	sysstty; arg
  4003                              <1> 	; Arguments:
  4004                              <1> 	;	arg - address of 3 consequitive words that contain
  4005                              <1> 	;	      the source of status data	
  4006                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4007                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4008                              <1> 	; ...............................................................
  4009                              <1> 	;	
  4010                              <1> 	; Retro UNIX 8086 v1 modification: 
  4011                              <1> 	;	'sysstty' system call will set the tty
  4012                              <1> 	;	(clear keyboard buffer and set cursor position)
  4013                              <1> 	;	 in following manner:
  4014                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4015                              <1> 	;
  4016                              <1> 	; Inputs:
  4017                              <1> 	;	BX = 0 --> means
  4018                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4019                              <1> 	;	      set cursor position for console tty, only 
  4020                              <1> 	;	      CH will be ignored (char. will not be written)	
  4021                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4022                              <1> 	;	      set console tty for (current) process
  4023                              <1> 	;	      CL = tty number (0 to 9)
  4024                              <1> 	;	      (If CH = 0, character will not be written)
  4025                              <1> 	;          If CH > 0 (CL < FFh)	
  4026                              <1> 	;             CL = tty number (0 to 9)
  4027                              <1> 	;	      CH = character will be written
  4028                              <1> 	;	        at requested cursor position (in DX)	
  4029                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4030                              <1>   	;		(only tty number 0 to 7) 
  4031                              <1> 	;          DL = communication parameters (for serial ports) 
  4032                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4033                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4034                              <1> 	;			or set cursor position	
  4035                              <1> 	;	   DH = 0FFh -> DL is not valid
  4036                              <1> 	;		do not set serial port parameters 
  4037                              <1> 	;		or do not set cursor position
  4038                              <1> 	;
  4039                              <1> 	;	BX > 0 --> points to name of tty
  4040                              <1> 	;    	   CH > 0 -->
  4041                              <1> 	;		CH = character will be written in current 
  4042                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4043                              <1> 	;	     	or character will be sent to serial port
  4044                              <1> 	;	     	(for tty number 8 or 9)
  4045                              <1> 	;		CL = color of the character if tty number < 8.
  4046                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4047                              <1> 	;		set mode (tty 8 to 9) or 
  4048                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4049                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4050                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4051                              <1> 	;		(DL is not valid)
  4052                              <1> 	;	   DL = communication parameters 
  4053                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4054                              <1> 	;
  4055                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4056                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4057                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4058                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4059                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4060                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4061                              <1> 	;
  4062                              <1> 	; Outputs:
  4063                              <1> 	;	cf = 0 -> OK
  4064                              <1> 	;	     AL = tty number (0 to 9)
  4065                              <1> 	;	     AH = line status if tty number is 8 or 9
  4066                              <1> 	;	     AH = process number (of the caller) 	
  4067                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4068                              <1> 	;	     AH = FFh if the tty is locked 
  4069                              <1> 	;		  (owned by another process)
  4070                              <1> 	;	        = process number (of the caller) 
  4071                              <1> 	;		  (if < FFh and tty number < 8)
  4072                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4073                              <1> 	;	     AH = line status if tty number is 8 or 9
  4074                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4075                              <1> 	;	
  4076                              <1> 
  4077                              <1> 	; 27/06/2015 (32 bit modifications)
  4078                              <1> 	; 14/01/2014
  4079 000037B8 31C0                <1> 	xor 	eax, eax
  4080 000037BA 6648                <1> 	dec	ax ; 17/10/2015
  4081 000037BC A3[10660000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4082                              <1> 	;;;
  4083                              <1> 	; 01/02/2022
  4084 000037C1 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4085 000037C3 39C2                <1> 	cmp	edx, eax
  4086                              <1> 	;cmp	dx, ax ; 0FFFFh
  4087 000037C5 7521                <1> 	jne	short sysstty_18
  4088                              <1> 	; clear video page
  4089                              <1> 	; (CH must be 0)
  4090 000037C7 08ED                <1> 	or	ch, ch
  4091 000037C9 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4092 000037CB 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4093 000037CE 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4094 000037D0 20C9                <1> 	and	cl, cl
  4095 000037D2 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4096 000037D4 0FB635[59660000]    <1> 	movzx	esi, byte [u.uno]
  4097 000037DB 8A8E[63630000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4098 000037E1 80F907              <1> 	cmp	cl, 7
  4099 000037E4 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4100                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4101 000037E6 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4102                              <1> sysstty_18:
  4103 000037E8 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4104                              <1> 	; cl = video page (tty) number		
  4105                              <1> 	;;;
  4106 000037EA 21DB                <1> 	and	ebx, ebx
  4107                              <1> 	;jnz	sysstty_6
  4108                              <1> 	; 01/02/2022
  4109 000037EC 7405                <1> 	jz	short sysstty_19
  4110 000037EE E9C2000000          <1> 	jmp	sysstty_6
  4111                              <1> sysstty_19:
  4112                              <1> 	; set console tty
  4113                              <1> 	; 29/10/2015
  4114                              <1> 	; 17/01/2014 
  4115 000037F3 80F909              <1> 	cmp	cl, 9
  4116 000037F6 7613                <1> 	jna	short sysstty_0
  4117                              <1> 	; 17/11/2015
  4118 000037F8 80F9FF              <1> 	cmp	cl, 0FFh
  4119 000037FB 7202                <1> 	jb	short sysstty_13
  4120 000037FD 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4121                              <1> sysstty_13:
  4122 000037FF 8A1D[59660000]      <1> 	mov	bl, [u.uno] ; process number
  4123 00003805 8A8B[63630000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4124                              <1> sysstty_0:
  4125                              <1> 	; 29/06/2015
  4126                              <1> 	;push	dx
  4127                              <1> 	;push	cx
  4128                              <1> 	; 01/02/2022
  4129 0000380B 52                  <1> 	push	edx
  4130 0000380C 51                  <1> 	push	ecx
  4131 0000380D 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4132 0000380F 88C8                <1> 	mov	al, cl
  4133 00003811 A2[10660000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4134 00003816 E8F6190000          <1> 	call	ottyp
  4135                              <1> 	; 01/02/2022
  4136 0000381B 59                  <1> 	pop	ecx
  4137 0000381C 5A                  <1> 	pop	edx
  4138                              <1> 	;pop	cx
  4139                              <1> 	;pop	dx
  4140                              <1> 	;
  4141 0000381D 7220                <1> 	jc	short sysstty_pd_err
  4142                              <1> 	;
  4143                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4144                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4145                              <1> 	;
  4146 0000381F 80F908              <1> 	cmp	cl, 8
  4147 00003822 720C                <1> 	jb	short sysstty_2
  4148                              <1> 	;
  4149 00003824 80FEFF              <1> 	cmp	dh, 0FFh
  4150 00003827 7407                <1> 	je	short sysstty_2
  4151                              <1> 		; set communication parameters for serial ports
  4152                              <1> 
  4153                              <1> ; 01/02/2022
  4154                              <1> ;	; 29/10/2015
  4155                              <1> ;	mov	ah, dl ; communication parameters
  4156                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4157                              <1> ;		;			 THRE int + RDA int 
  4158                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4159                              <1> ;		;			 THRE int + RDA int 
  4160                              <1> ;	sub	al, al ; 0
  4161                              <1> ;	; 12/07/2014
  4162                              <1> ;	cmp	cl, 9
  4163                              <1> ;	jb	short sysstty_1
  4164                              <1> ;	inc	al
  4165                              <1> ;sysstty_1:
  4166                              <1> ;	; 01/02/2022
  4167                              <1> ;	push	ecx
  4168                              <1> ;	;push	cx
  4169                              <1> ;	; 29/06/2015	
  4170                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4171                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4172                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4173                              <1> ;	; 01/02/2022
  4174                              <1> ;	pop	ecx	
  4175                              <1> ;	;pop	cx
  4176                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4177                              <1> 
  4178                              <1> 	; 01/02/2022
  4179 00003829 E832010000          <1> 	call	sysstty_scp
  4180 0000382E 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4181                              <1> 
  4182                              <1> sysstty_2:
  4183                              <1> 	; 17/01/2014
  4184 00003830 20ED                <1> 	and	ch, ch 	; set cursor position 
  4185                              <1> 			; or comm. parameters ONLY
  4186 00003832 7527                <1> 	jnz	short sysstty_3
  4187                              <1> 	; 01/02/2022
  4188 00003834 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4189 00003838 7214                <1> 	jb	short sysstty_20
  4190                              <1> 	; clear screen (video page)
  4191 0000383A E93D010000          <1> 	jmp	sysstty_14
  4192                              <1> 
  4193                              <1> sysstty_pd_err: ; 29/06/2015
  4194                              <1> 	; 'permission denied !' error
  4195 0000383F C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4195 00003847 0000                <1>
  4196 00003849 E9B9F9FFFF          <1> 	jmp	error
  4197                              <1> 
  4198                              <1> sysstty_20:
  4199 0000384E 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4200 00003855 888B[63630000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4201                              <1> sysstty_3:
  4202                              <1> 	; 16/01/2014
  4203 0000385B 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4204                              <1> 	; 17/11/2015
  4205 0000385D B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4206 0000385F 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4207                              <1> 	;jna	sysstty_9
  4208                              <1> 	; 01/02/2022
  4209 00003861 7705                <1> 	ja	short sysstty_12
  4210 00003863 E9C7000000          <1> 	jmp	sysstty_9
  4211                              <1> 
  4212                              <1> sysstty_12:
  4213                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4214                              <1> 	; (Set specified serial port as console tty port)
  4215                              <1> 	; CH = character to be written
  4216                              <1> 	; 15/04/2014
  4217                              <1> 	; CH = 0 --> initialization only
  4218                              <1> 	; AL = character
  4219                              <1> 	; 26/06/2014
  4220 00003868 880D[5E660000]      <1> 	mov	[u.ttyn], cl
  4221                              <1> 	; 12/07/2014
  4222 0000386E 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4223                              <1> 	; 02/02/2022
  4224 00003870 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4225 00003872 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4226 00003874 FEC8                <1> 	dec	al  ; 1 -> 0	
  4227                              <1> 	;and	al, al
  4228 00003876 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4229                              <1>  	; 04/07/2014
  4230 00003878 E8A21E0000          <1> 	call 	sndc
  4231                              <1> 	; 12/07/2014
  4232 0000387D EB0C                <1> 	jmp	short sysstty_5
  4233                              <1> 
  4234                              <1> sysstty_4:
  4235                              <1> 	; 12/07/2014
  4236                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4237 0000387F 88E0                <1> 	mov	al, ah ; 29/06/2015
  4238 00003881 2C08                <1> 	sub	al, 8
  4239                              <1> 	; 27/06/2015
  4240 00003883 E832F4FFFF          <1> 	call	sp_status ; get serial port status
  4241                              <1> 	; AL = Line status, AH = Modem status
  4242                              <1> 	; 12/11/2015
  4243 00003888 3C80                <1> 	cmp	al, 80h
  4244 0000388A F5                  <1> 	cmc
  4245                              <1> sysstty_5:
  4246 0000388B 66A3[11660000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4247                              <1> 		; EAX bits 16-23 = modem status	
  4248 00003891 9C                  <1> 	pushf
  4249 00003892 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4250 00003894 A0[5E660000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4251 00003899 E8961A0000          <1> 	call	cttyp
  4252 0000389E 9D                  <1> 	popf
  4253                              <1> 	;jnc	sysret ; time out error 
  4254                              <1> 	; 01/02/2022
  4255 0000389F 7205                <1> 	jc	short sysstty_tmout_err
  4256 000038A1 E981F9FFFF          <1> 	jmp	sysret
  4257                              <1> 
  4258                              <1> sysstty_tmout_err:
  4259 000038A6 C705[5F660000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4259 000038AE 0000                <1>
  4260 000038B0 E952F9FFFF          <1> 	jmp	error
  4261                              <1> 
  4262                              <1> sysstty_6:
  4263                              <1> 	;push	dx
  4264                              <1> 	;push	cx
  4265                              <1> 	; 01/02/2022
  4266 000038B5 52                  <1> 	push	edx
  4267 000038B6 51                  <1> 	push	ecx
  4268 000038B7 891D[28660000]      <1> 	mov	[u.namep], ebx
  4269 000038BD E846080000          <1> 	call	namei
  4270                              <1> 	; 01/02/2022
  4271 000038C2 59                  <1> 	pop	ecx
  4272 000038C3 5A                  <1> 	pop	edx
  4273                              <1> 	;pop	cx
  4274                              <1> 	;pop	dx
  4275 000038C4 725A                <1> 	jc	short sysstty_inv_dn
  4276                              <1> 	;
  4277 000038C6 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4278 000038CA 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4279                              <1> 	;
  4280 000038CC 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4281                              <1> 		       ; /dev/COM1, /dev/COM2
  4282 000038CE 7206                <1> 	jb	short sysstty_7
  4283 000038D0 2C0A                <1> 	sub	al, 10
  4284                              <1> 	; al = 0 to 9
  4285 000038D2 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4286 000038D4 EB11                <1> 	jmp	short sysstty_8
  4287                              <1> 
  4288                              <1> sysstty_7:
  4289 000038D6 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4290 000038D8 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4291 000038DA 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4292 000038E1 8A83[63630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4293                              <1> sysstty_8:
  4294                              <1> 	; 22/02/2022
  4295                              <1> 	; (ebx < 256)
  4296 000038E7 A2[10660000]        <1> 	mov	[u.r0], al
  4297                              <1> 	; 01/02/2022
  4298                              <1> 	;push	dx
  4299                              <1> 	;push	ax
  4300                              <1> 	;push	cx
  4301 000038EC 52                  <1> 	push	edx
  4302 000038ED 50                  <1> 	push	eax
  4303 000038EE 51                  <1> 	push	ecx
  4304 000038EF E81D190000          <1> 	call	ottyp
  4305 000038F4 59                  <1> 	pop	ecx
  4306 000038F5 58                  <1> 	pop	eax
  4307 000038F6 5A                  <1> 	pop	edx
  4308                              <1> 	;pop	cx
  4309                              <1> 	;pop	ax
  4310                              <1> 	;pop	dx
  4311                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4312                              <1> 	; 01/02/2022
  4313 000038F7 7305                <1> 	jnc	short sysstty_21
  4314 000038F9 E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4315                              <1> sysstty_21:
  4316                              <1> 	; 29/10/2015
  4317 000038FE 86E9                <1> 	xchg 	ch, cl
  4318                              <1> 		; cl = character, ch = color code
  4319 00003900 86C1                <1> 	xchg	al, cl
  4320                              <1> 		; al = character, cl = tty number
  4321 00003902 80F907              <1> 	cmp	cl, 7
  4322                              <1> 	;ja	sysstty_12
  4323                              <1> 	; 01/02/2022
  4324 00003905 7628                <1> 	jna	short sysstty_16
  4325                              <1> ;;
  4326 00003907 80FEFF              <1> 	cmp	dh, 0FFh
  4327 0000390A 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4328                              <1> 
  4329                              <1> ; 01/02/2022
  4330                              <1> ;	; 29/10/2015
  4331                              <1> ;	mov	ah, dl ; communication parameters
  4332                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4333                              <1> ;		;			 THRE int + RDA int 
  4334                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4335                              <1> ;		;			 THRE int + RDA int 
  4336                              <1> ;	sub	al, al ; 0
  4337                              <1> ;	; 12/07/2014
  4338                              <1> ;	cmp	cl, 9
  4339                              <1> ;	jb	short sysstty_1
  4340                              <1> ;	inc	al
  4341                              <1> ;sysstty_1:
  4342                              <1> ;	; 01/02/2022
  4343                              <1> ;	push	ecx
  4344                              <1> ;	;push	cx
  4345                              <1> ;	; 29/06/2015	
  4346                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4347                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4348                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4349                              <1> ;	; 01/02/2022
  4350                              <1> ;	pop	ecx	
  4351                              <1> ;	;pop	cx
  4352                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4353                              <1> 
  4354                              <1> 	; 02/02/2022
  4355 0000390C 88C5                <1> 	mov	ch, al ; save char
  4356                              <1> 	; 01/02/2022
  4357 0000390E E84D000000          <1> 	call	sysstty_scp
  4358 00003913 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4359                              <1> 	; 02/02/2022
  4360 00003915 88E8                <1> 	mov	al, ch ; restore char
  4361                              <1> sysstty_22:
  4362                              <1> 	; 01/02/2022
  4363 00003917 08ED                <1> 	or	ch, ch
  4364 00003919 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4365                              <1> 	; send char to (serial port) terminal
  4366                              <1> 	; al = character
  4367                              <1> 	; cl = tty number (8 or 9)
  4368 0000391B E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4369                              <1> 
  4370                              <1> sysstty_inv_dn: 
  4371                              <1> 	; 27/06/2015
  4372                              <1> 	; Invalid device name (not a tty) ! error
  4373                              <1> 	; (Device is not a tty or device name not found)
  4374 00003920 C705[5F660000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4374 00003928 0000                <1>
  4375 0000392A E9D8F8FFFF          <1> 	jmp	error 
  4376                              <1> 
  4377                              <1> sysstty_16:
  4378                              <1> 	; 22/02/2022
  4379                              <1> 	; 16/01/2014
  4380                              <1> 	;xor	bh, bh
  4381                              <1> sysstty_9: 	; tty 0 to tty 7
  4382                              <1> 	; al = character
  4383                              <1> 	; ch = color/attribute ; 01/02/2022
  4384                              <1> 	;
  4385                              <1>  	; 22/02/2022 (BugFix)
  4386                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4387 0000392F 29DB                <1> 	sub	ebx, ebx ; *
  4388 00003931 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4389                              <1> 	;
  4390 00003933 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4391 00003936 7409                <1> 	je	short sysstty_10
  4392                              <1> 	; 02/02/2022
  4393 00003938 51                  <1> 	push	ecx
  4394 00003939 50                  <1> 	push	eax
  4395                              <1> 	;push	cx
  4396                              <1> 	;push	ax	
  4397                              <1> 	; 22/02/2022	
  4398                              <1> 	;;movzx	ebx, cl ; *
  4399                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4400 0000393A E887DBFFFF          <1> 	call	set_cpos
  4401                              <1> 	;pop	ax
  4402                              <1> 	;pop	cx
  4403                              <1> 	; 02/02/2022
  4404 0000393F 58                  <1> 	pop	eax
  4405 00003940 59                  <1> 	pop	ecx
  4406                              <1> sysstty_10: 
  4407                              <1> 	; 29/10/2015
  4408 00003941 08C0                <1> 	or	al, al ; character
  4409 00003943 740D                <1> 	jz      short sysstty_11 ; al = 0
  4410                              <1> 	; 17/11/2015
  4411 00003945 3CFF                <1> 	cmp	al, 0FFh
  4412 00003947 7309                <1> 	jnb	short sysstty_11
  4413                              <1> 		; ch > 0 and ch < FFh
  4414                              <1> 	; write a character at current cursor position
  4415 00003949 88EC                <1> 	mov	ah, ch ; color/attribute
  4416                              <1> 	; 12/07/2014
  4417                              <1> 	;push	cx
  4418                              <1> 	; 02/02/2022
  4419 0000394B 51                  <1> 	push	ecx
  4420 0000394C E85DDCFFFF          <1> 	call	write_c_current
  4421                              <1> 	;pop	cx
  4422                              <1> 	; 02/02/2022
  4423 00003951 59                  <1> 	pop	ecx
  4424                              <1> sysstty_11:
  4425                              <1> 	; 14/01/2014
  4426 00003952 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4427                              <1> 	; 18/01/2014
  4428                              <1> 	;movzx	eax, cl ; 27/06/2015
  4429 00003954 88C8                <1> 	mov	al, cl
  4430 00003956 E8D9190000          <1> 	call	cttyp
  4431 0000395B E9C7F8FFFF          <1> 	jmp	sysret
  4432                              <1> 
  4433                              <1> sysstty_scp:
  4434                              <1> 	; 02/02/2022
  4435                              <1> 	; set communication parameters (for COM1 or COM2)
  4436                              <1> 	; 01/02/2022
  4437                              <1> 	;
  4438                              <1> 	; 29/10/2015
  4439 00003960 88D4                <1> 	mov	ah, dl ; communication parameters
  4440                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4441                              <1> 		;			 THRE int + RDA int 
  4442                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4443                              <1> 		;			 THRE int + RDA int 
  4444 00003962 28C0                <1> 	sub	al, al ; 0
  4445                              <1> 	; 12/07/2014
  4446 00003964 80F909              <1> 	cmp	cl, 9
  4447 00003967 7202                <1> 	jb	short sysstty_1
  4448 00003969 FEC0                <1> 	inc	al
  4449                              <1> sysstty_1:
  4450                              <1> 	; 02/02/2022
  4451 0000396B 52                  <1> 	push	edx
  4452                              <1> 	; 01/02/2022
  4453 0000396C 51                  <1> 	push	ecx
  4454                              <1> 	;push	cx
  4455                              <1> 	; 29/06/2015	
  4456 0000396D E850F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4457 00003972 66890D[11660000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4458                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4459                              <1> 	; 01/02/2022
  4460 00003979 59                  <1> 	pop	ecx	
  4461                              <1> 	;pop	cx
  4462 0000397A 5A                  <1> 	pop	edx ; 02/02/2022
  4463                              <1> 	; 01/02/2022
  4464                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4465 0000397B C3                  <1> 	retn
  4466                              <1> 
  4467                              <1> sysstty_14:
  4468                              <1> 	; 23/02/2022
  4469                              <1> 	; 02/02/2022
  4470                              <1> 	; ch = 0
  4471                              <1> 	; cl = video page
  4472                              <1> 	;
  4473                              <1> 	; dx = 0FFFFh
  4474                              <1> 	; clear screen (video page)
  4475                              <1> 	;
  4476                              <1> 
  4477                              <1> 	; 02/02/2022
  4478                              <1> 	; clear screen
  4479                              <1> 	;
  4480                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4481                              <1> 
  4482                              <1> 	; 23/02/2022
  4483 0000397C 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4484                              <1> 
  4485                              <1> 	; clear video page
  4486 0000397E E810000000          <1> 	call	wttyc ; 23/02/2022
  4487                              <1> 
  4488                              <1> 	; 23/02/2022
  4489 00003983 88D8                <1> 	mov	al, bl
  4490 00003985 8A25[59660000]      <1> 	mov	ah, [u.uno]
  4491 0000398B 66A3[10660000]      <1> 	mov	[u.r0], ax
  4492 00003991 EBBF                <1> 	jmp	short sysstty_11
  4493                              <1> 
  4494                              <1> vp_clr:	; 27/02/2022
  4495                              <1> wttyc:
  4496                              <1> 	; 23/02/2022
  4497                              <1> 	; (clear video page)
  4498                              <1> 	; INPUT:
  4499                              <1> 	;  bl = video page (0 to 7)
  4500                              <1> 	;
  4501                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4502                              <1> 
  4503                              <1> 	;xor	dx, dx ; column 0, row 0
  4504                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4505                              <1> 	;
  4506                              <1> ;	movzx	ebx, cl
  4507                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4508                              <1> 
  4509                              <1> ;	shl 	bl, 1 
  4510                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4511                              <1> ;		; AL = lock value (0 or process number)
  4512                              <1> ;	or	al, al
  4513                              <1> ;	jz	short @f
  4514                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4515                              <1> ;	jne	short sysstty_15
  4516                              <1> ;		; only the owner can clear its video page
  4517                              <1> ;	xor	al, al ; 0
  4518                              <1> ;@@:
  4519                              <1> ;	;mov	bl, cl		
  4520                              <1> ;	shr	bl, 1 
  4521                              <1> 
  4522 00003993 30C0                <1> 	xor	al, al	; 0
  4523 00003995 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4524                              <1> 
  4525                              <1> 	; scroll_up input:
  4526                              <1> 	;
  4527                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4528                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4529                              <1> 	; ah = attribute to be used on blanked line
  4530                              <1> 	; bl = video page number (0 to 7)
  4531                              <1> 
  4532 00003997 E8B0DBFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4533                              <1> 
  4534                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4535                              <1> 
  4536                              <1> 	; bl = video page number (0 to 7)
  4537                              <1> 	;xor	dx, dx ; column 0, row 0
  4538                              <1> 	; 02/02/2022
  4539 0000399C 31D2                <1> 	xor	edx, edx
  4540                              <1> 	; 23/02/2022
  4541                              <1> 	;call	set_cpos
  4542                              <1> 	;retn
  4543 0000399E E923DBFFFF          <1> 	jmp	set_cpos
  4544                              <1> 
  4545                              <1> 	;mov	al, bl
  4546                              <1> 	;mov	ah, [u.uno]
  4547                              <1> 	;mov	[u.r0], ax
  4548                              <1> 	;jmp	short sysstty_11
  4549                              <1> 
  4550                              <1> ;sysstty_15:
  4551                              <1> ;	; 30/01/2022
  4552                              <1> ;	; permission (denied) error
  4553                              <1> ;	;xor	dl, dl ; sysstty call sign
  4554                              <1> ;	mov	al, cl
  4555                              <1> ;	sub	ah, ah ; 0
  4556                              <1> ;	call	cttyp
  4557                              <1> ;	jmp	error
  4558                              <1> 
  4559                              <1> ; Original UNIX v1 'sysstty' routine:
  4560                              <1> ; gtty:
  4561                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4562                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4563                              <1> 	; 		/ r2 has source
  4564                              <1>         ;mov    r2,-(sp)
  4565                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4566                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4567                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4568                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4569                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4570                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4571                              <1>         ;       br .+4 / list empty, skip branch
  4572                              <1>         ;br     1b / get another character until list is empty
  4573                              <1>         ;mov    0b,r1 / move cc offset to r1
  4574                              <1>         ;inc    r1 / bump it for output clist
  4575                              <1>         ;tstb   cc(r1) / is it 0
  4576                              <1>         ;beq    1f / yes, no characters to output
  4577                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4578                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4579                              <1>         ;br     1b / try to calm it down again
  4580                              <1> ;1:
  4581                              <1>         ;mov    (sp)+,r1
  4582                              <1>         ;mov    (sp)+,r2 / restore registers
  4583                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4584                              <1>         ;beq    1f / if 0, 1f
  4585                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4586                              <1>         ;                   / control status register
  4587                              <1> ;1:
  4588                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4589                              <1>         ;beq    1f / if 0 1f
  4590                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4591                              <1> 	;		    / control status reg
  4592                              <1> ;1:
  4593                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4594                              <1>         ;jmp	sysret2 / return to user
  4595                              <1> 
  4596                              <1> sysgtty: ; < get tty status >
  4597                              <1> 	; 22/02/2022
  4598                              <1> 	; 01/02/2022
  4599                              <1> 	; 23/11/2015
  4600                              <1> 	; 29/10/2015
  4601                              <1> 	; 17/10/2015
  4602                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4603                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4604                              <1> 	;
  4605                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4606                              <1> 	; It stores in the three words addressed by it's argument
  4607                              <1> 	; the status of the typewriter whose file descriptor
  4608                              <1> 	; in (u.r0).
  4609                              <1> 	;
  4610                              <1> 	; Calling sequence:
  4611                              <1> 	;	sysgtty; arg
  4612                              <1> 	; Arguments:
  4613                              <1> 	;	arg - address of 3 words destination of the status
  4614                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4615                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4616                              <1> 	; ...............................................................
  4617                              <1> 	;	
  4618                              <1> 	; Retro UNIX 8086 v1 modification: 
  4619                              <1> 	;	'sysgtty' system call will return status of tty
  4620                              <1> 	;	(keyboard, serial port and video page status)
  4621                              <1> 	;	 in following manner:
  4622                              <1> 	;
  4623                              <1> 	; Inputs:
  4624                              <1> 	;	BX = 0 --> means 
  4625                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4626                              <1> 	;	                 for (current) process
  4627                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4628                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4629                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4630                              <1> 	;	     CH > 0 -->	tty number + 1
  4631                              <1> 	;
  4632                              <1> 	;	BX > 0 --> points to name of tty
  4633                              <1> 	;	     CL = 0 --> return keyboard status
  4634                              <1> 	;	     CL = 1 --> return video page status
  4635                              <1> 	;	     CH = undefined		 
  4636                              <1> 	;
  4637                              <1> 	; Outputs:
  4638                              <1> 	;	cf = 0 ->
  4639                              <1> 	;
  4640                              <1> 	;	     AL = tty number from 0 to 9
  4641                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4642                              <1> 	;	     AH = 0 if the tty is free/unused
  4643                              <1> 	;	     AH = the process number of the caller 
  4644                              <1>  	;	     AH = FFh if the tty is locked by another process
  4645                              <1> 	;
  4646                              <1> 	;	  (if calling is for serial port status)
  4647                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4648                              <1> 	;		  (BH = modem status, BL = Line status)
  4649                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4650                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4651                              <1> 	;
  4652                              <1> 	;	  (if calling is for keyboard status)
  4653                              <1> 	;	     BX = current character in tty/keyboard buffer
  4654                              <1> 	;		  (BH = scan code, BL = ascii code)
  4655                              <1> 	;		  (BX=0 if there is not a waiting character)
  4656                              <1> 	;	     CX  is undefined
  4657                              <1> 	;
  4658                              <1> 	;	  (if calling is for video page status)	
  4659                              <1> 	;	     BX = cursor position on the video page
  4660                              <1> 	;		  if tty number < 8
  4661                              <1> 	;		  (BH = row, BL = column)
  4662                              <1> 	;	     CX = current character (in cursor position)
  4663                              <1> 	;		  on the video page of the tty 
  4664                              <1> 	;		  if tty number < 8
  4665                              <1> 	;		  (CH = color, CL = character)
  4666                              <1> 	;	
  4667                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4668                              <1> 	;
  4669                              <1> 	;	     AH = FFh if the caller is not owner of
  4670                              <1> 	;		  specified tty or console tty
  4671                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4672                              <1> 	;	     BX, CX are undefined if cf = 1
  4673                              <1> 	;
  4674                              <1> 	;	  (If tty number is 8 or 9)
  4675                              <1> 	;	     AL = tty number 
  4676                              <1> 	;	     AH = the process number of the caller 
  4677                              <1> 	;	     BX = serial port status
  4678                              <1> 	;  		 (BH = modem status, BL = Line status)
  4679                              <1> 	;	     CX = 0
  4680                              <1> 	;
  4681                              <1> 		
  4682                              <1> gtty:   ; get (requested) tty number
  4683                              <1> 	; 22/02/2022
  4684                              <1> 	; 01/02/2022
  4685                              <1> 	; 17/10/2015
  4686                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4687                              <1> 	; 30/05/2013 - 12/07/2014
  4688                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4689                              <1> 	;
  4690                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4691                              <1> 	;
  4692                              <1> 	; 28/06/2015 (32 bit modifications)
  4693                              <1> 	; 16/01/2014
  4694 000039A3 31C0                <1> 	xor 	eax, eax
  4695 000039A5 6648                <1> 	dec	ax ; 17/10/2015
  4696 000039A7 A3[10660000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4697 000039AC 80F901              <1> 	cmp	cl, 1
  4698 000039AF 760F                <1> 	jna	short sysgtty_0
  4699                              <1> sysgtty_invp:
  4700                              <1> 	; 28/06/2015
  4701 000039B1 C705[5F660000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4701 000039B9 0000                <1>
  4702 000039BB E947F8FFFF          <1> 	jmp	error
  4703                              <1> sysgtty_0:	
  4704 000039C0 21DB                <1> 	and	ebx, ebx
  4705 000039C2 742E                <1> 	jz	short sysgtty_1
  4706                              <1> 	;
  4707 000039C4 891D[28660000]      <1> 	mov	[u.namep], ebx
  4708                              <1> 	;push	cx ; 23/11/2015
  4709                              <1> 	; 01/02/2022
  4710 000039CA 51                  <1> 	push	ecx
  4711 000039CB E838070000          <1> 	call	namei
  4712                              <1> 	; 01/02/2022
  4713 000039D0 59                  <1> 	pop	ecx
  4714                              <1> 	;pop	cx ; 23/11/2015
  4715 000039D1 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4716                              <1> 	;
  4717 000039D3 6683F801            <1> 	cmp	ax, 1
  4718 000039D7 7622                <1> 	jna	short sysgtty_2
  4719                              <1> 	; 01/02/2022
  4720 000039D9 20E4                <1> 	and	ah, ah
  4721 000039DB 7506                <1> 	jnz	short sysgtty_inv_dn
  4722                              <1> 	;sub	ax, 10
  4723 000039DD 2C0A                <1> 	sub	al, 10
  4724 000039DF 3C09                <1> 	cmp	al, 9
  4725                              <1> 	;cmp	ax, 9
  4726                              <1> 	;ja	short sysgtty_inv_dn
  4727                              <1> 	;mov	ch, al
  4728                              <1> 	;jmp	short sysgtty_4
  4729                              <1> 	; 23/11/2015
  4730 000039E1 7629                <1> 	jna	short sysgtty_4
  4731                              <1> sysgtty_inv_dn: 
  4732                              <1> 	; 28/06/2015
  4733                              <1> 	; Invalid device name (not a tty) ! error
  4734                              <1> 	; (Device is not a tty or device name not found)
  4735 000039E3 C705[5F660000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4735 000039EB 0000                <1>
  4736 000039ED E915F8FFFF          <1> 	jmp	error 
  4737                              <1> sysgtty_1:
  4738                              <1> 	; 16/01/2014
  4739 000039F2 80FD0A              <1> 	cmp	ch, 10
  4740 000039F5 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4741 000039F7 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4742 000039F9 790F                <1> 	jns	short sysgtty_3 ; not negative
  4743                              <1> 	;
  4744                              <1> sysgtty_2:
  4745                              <1> 	; get tty number of console tty
  4746 000039FB 8A25[59660000]      <1> 	mov	ah, [u.uno]
  4747                              <1>  	; 28/06/2015
  4748 00003A01 0FB6DC              <1> 	movzx 	ebx, ah
  4749 00003A04 8AAB[63630000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4750                              <1> sysgtty_3:
  4751 00003A0A 88E8                <1> 	mov	al, ch
  4752                              <1> sysgtty_4:
  4753 00003A0C A2[10660000]        <1> 	mov	[u.r0], al
  4754                              <1>  	; 28/06/2015
  4755                              <1> 	;cmp	al, 9
  4756                              <1> 	;ja	short sysgtty_invp
  4757 00003A11 8B2D[0C660000]      <1> 	mov	ebp, [u.usp]
  4758                              <1> 	; 23/11/2015
  4759 00003A17 20C9                <1> 	and	cl, cl
  4760 00003A19 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4761 00003A1B 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4762 00003A1D 722E                <1> 	jb	short sysgtty_6 ; video page status
  4763                              <1> 	; serial port status
  4764                              <1> 	; 12/07/2014
  4765                              <1> 	;mov	dx, 0
  4766                              <1> 	;je	short sysgtty_5
  4767                              <1> 	;inc	dl
  4768                              <1> ;sysgtty_5:
  4769                              <1> 	; 28/06/2015
  4770 00003A1F 2C08                <1> 	sub	al, 8
  4771 00003A21 E894F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4772                              <1> 	; AL = Line status, AH = Modem status
  4773 00003A26 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4774 00003A2A 8A25[59660000]      <1> 	mov	ah, [u.uno]
  4775 00003A30 8825[11660000]      <1>         mov     [u.r0+1], ah
  4776 00003A36 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4777                              <1> 				; (in ECX)
  4778 00003A3C A880                <1> 	test	al, 80h
  4779 00003A3E 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4780 00003A40 A801                <1> 	test	al, 1
  4781                              <1> 	;jz	sysret
  4782 00003A42 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4783 00003A44 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4784                              <1> sysgtty_10:
  4785 00003A48 E9DAF7FFFF          <1> 	jmp	sysret
  4786                              <1> sysgtty_6:
  4787 00003A4D A2[5E660000]        <1> 	mov	[u.ttyn], al ; tty number
  4788                              <1> 	;movzx	ebx, al
  4789 00003A52 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4790 00003A54 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4791                              <1> 	; 22/04/2014 - 29/06/2015
  4792 00003A56 81C3[94620000]      <1>         add     ebx, ttyl
  4793 00003A5C 8A23                <1>  	mov	ah, [ebx]
  4794 00003A5E 3A25[59660000]      <1> 	cmp	ah, [u.uno]
  4795 00003A64 7404                <1> 	je	short sysgtty_7
  4796 00003A66 20E4                <1> 	and	ah, ah
  4797                              <1> 	;jz	short sysgtty_7
  4798 00003A68 7506                <1> 	jnz	short sysgtty_8
  4799                              <1> 	;mov	ah, 0FFh
  4800                              <1> sysgtty_7:
  4801 00003A6A 8825[11660000]      <1>         mov     [u.r0+1], ah
  4802                              <1> sysgtty_8:
  4803 00003A70 08C9                <1> 	or	cl, cl
  4804 00003A72 7510                <1> 	jnz	short sysgtty_9
  4805 00003A74 B001                <1> 	mov	al, 1  ; test a key is available
  4806 00003A76 E8271C0000          <1> 	call	getc
  4807 00003A7B 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4808 00003A7F E9A3F7FFFF          <1> 	jmp	sysret
  4809                              <1> sysgtty_9:
  4810 00003A84 8A1D[5E660000]      <1> 	mov	bl, [u.ttyn]
  4811                              <1> 	; bl = video page number
  4812 00003A8A E8841D0000          <1> 	call 	get_cpos
  4813                              <1> 	; dx = cursor position
  4814 00003A8F 66895510            <1> 	mov	[ebp+16], dx ; bx
  4815                              <1> 	;mov	bl, [u.ttyn]
  4816                              <1> 	; bl = video page number
  4817 00003A93 E88C1D0000          <1> 	call	read_ac_current
  4818                              <1> 	; ax = character and attribute/color
  4819 00003A98 66894518            <1> 	mov	[ebp+24], ax ; cx
  4820 00003A9C E986F7FFFF          <1> 	jmp	sysret
  4821                              <1> sysgtty_dnr_err:
  4822                              <1> 	; 'device not responding !' error	
  4823                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4824 00003AA1 C705[5F660000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4824 00003AA9 0000                <1>
  4825 00003AAB E957F7FFFF          <1> 	jmp	error	
  4826                              <1> 
  4827                              <1> ; Original UNIX v1 'sysgtty' routine:
  4828                              <1> ; sysgtty:
  4829                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4830                              <1> 	;	       / r2 has destination
  4831                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4832                              <1> 	;                     / in 1st word of dest
  4833                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4834                              <1> 	;                     / in 2nd word of dest
  4835                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4836                              <1>         ;jmp    sysret2 / return to user
  4837                              <1> 	
  4838                              <1> ; Original UNIX v1 'gtty' routine:
  4839                              <1> ; gtty:
  4840                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4841                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4842                              <1>         ;jsr    r0,getf / get the i-number of the file
  4843                              <1>         ;tst    r1 / is it open for reading
  4844                              <1>         ;bgt    1f / yes
  4845                              <1>         ;neg    r1 / no, i-number is negative, 
  4846                              <1> 	;          / so make it positive
  4847                              <1> ;1:
  4848                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4849                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4850                              <1>         ;bhis   error9 / no, error
  4851                              <1>         ;asl    r1 / 0%2
  4852                              <1>         ;asl    r1 / 0%4 / yes
  4853                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4854                              <1> 	;	       ; / tty block
  4855                              <1>         ;mov    u.off,r2 / put argument in r2
  4856                              <1>         ;rts    r0 / return
  2051                                  %include 'u2.s'        ; 11/05/2015
  2052                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS2.INC
  2053                              <1> ; Last Modification: 15/05/2022
  2054                              <1> ; ----------------------------------------------------------------------------
  2055                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2056                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2057                              <1> ;
  2058                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2059                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2060                              <1> ; <Bell Laboratories (17/3/1972)>
  2061                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2062                              <1> ;
  2063                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2064                              <1> ;
  2065                              <1> ; ****************************************************************************
  2066                              <1> ; 03/01/2016
  2067                              <1> 
  2068                              <1> syslink:
  2069                              <1> 	; 03/02/2022
  2070                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2071                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2072                              <1> 	;
  2073                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2074                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2075                              <1> 	; given to the entry that will go in the current directory.
  2076                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2077                              <1> 	; in the name 2 entry of current directory is the same
  2078                              <1> 	; i-number for the name 1 file.
  2079                              <1> 	;
  2080                              <1> 	; Calling sequence:
  2081                              <1> 	;	syslink; name 1; name 2
  2082                              <1> 	; Arguments:
  2083                              <1> 	;	name 1 - file name to which link will be created.
  2084                              <1> 	;	name 2 - name of entry in current directory that
  2085                              <1> 	;		 links to name 1.
  2086                              <1> 	; Inputs: -
  2087                              <1> 	; Outputs: -
  2088                              <1> 	; ...............................................................
  2089                              <1> 	;	
  2090                              <1> 	; Retro UNIX 8086 v1 modification: 
  2091                              <1> 	;       'syslink' system call has two arguments; so,
  2092                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2093                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2094                              <1> 	;
  2095                              <1> 		; / name1, name2
  2096                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2097 00003AB0 891D[28660000]      <1> 	mov	[u.namep], ebx
  2098 00003AB6 51                  <1> 	push	ecx
  2099 00003AB7 E84C060000          <1> 	call	namei
  2100                              <1> 		; jsr r0,namei / find the i-number associated with
  2101                              <1> 			     ; / the 1st path name
  2102                              <1>      	;;and	ax, ax
  2103                              <1> 	;;jz	error ; File not found
  2104                              <1> 	;jc	error 
  2105                              <1> 		; br error9 / cannot be found
  2106 00003ABC 730F                <1> 	jnc	short syslink0
  2107                              <1> 	;pop 	ecx
  2108                              <1> 	; 'file not found !' error
  2109 00003ABE C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2109 00003AC6 0000                <1>
  2110 00003AC8 E93AF7FFFF          <1> 	jmp	error
  2111                              <1> syslink0:
  2112 00003ACD E84B0E0000          <1> 	call	iget
  2113                              <1> 		; jsr r0,iget / get the i-node into core
  2114 00003AD2 8F05[28660000]      <1> 	pop	dword [u.namep] ; ecx
  2115                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2116                              <1> 	; 03/02/2022
  2117 00003AD8 50                  <1> 	push	eax
  2118                              <1> 	;push	ax
  2119                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2120                              <1> 			    ; / (a link to this file is to be created)
  2121 00003AD9 66FF35[F4650000]    <1> 	push	word [cdev]
  2122                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2123 00003AE0 E852000000          <1> 	call	isdir
  2124                              <1> 		; jsr r0,isdir / is it a directory
  2125 00003AE5 E81E060000          <1> 	call	namei
  2126                              <1> 		; jsr r0,namei / no, get i-number of name2
  2127                              <1> 	;jnc	error
  2128                              <1> 		; br .+4   / not found 
  2129                              <1> 			 ; / so r1 = i-number of current directory
  2130                              <1> 			 ; / ii = i-number of current directory
  2131                              <1> 		; br error9 / file already exists., error
  2132 00003AEA 720F                <1> 	jc	short syslink1
  2133                              <1> 	; pop ax
  2134                              <1> 	; pop ax
  2135                              <1> 	; 'file exists !' error
  2136 00003AEC C705[5F660000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2136 00003AF4 0000                <1>
  2137 00003AF6 E90CF7FFFF          <1> 	jmp	error
  2138                              <1> syslink1:
  2139 00003AFB 6659                <1> 	pop	cx
  2140                              <1> 	;cmp	cx, [cdev]
  2141 00003AFD 3A0D[F4650000]      <1> 	cmp	cl, [cdev]
  2142                              <1> 	;jne	error
  2143                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2144                              <1> 			       ; / end of current directory
  2145                              <1> 	        ; bne error9
  2146 00003B03 740F                <1> 	je	short syslink2
  2147                              <1> 	; 'not same drive !' error
  2148 00003B05 C705[5F660000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2148 00003B0D 0000                <1>
  2149 00003B0F E9F3F6FFFF          <1> 	jmp	error
  2150                              <1> syslink2:
  2151                              <1> 	;pop	ax
  2152                              <1> 	;push	ax
  2153                              <1> 	; 03/02/2022
  2154                              <1> 	;mov	eax, [esp]
  2155 00003B14 58                  <1> 	pop	eax
  2156 00003B15 50                  <1> 	push	eax
  2157 00003B16 66A3[42660000]      <1> 	mov	[u.dirbuf], ax
  2158                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2159 00003B1C E89E000000          <1> 	call	mkdir
  2160                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2161                              <1> 		 	     ; / in current directory
  2162                              <1> 	; 03/02/2022
  2163 00003B21 58                  <1> 	pop	eax
  2164                              <1> 	;pop	ax
  2165                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2166 00003B22 E8F60D0000          <1> 	call	iget
  2167                              <1> 		; jsr r0,iget / get i-node into core
  2168 00003B27 FE05[06630000]      <1> 	inc	byte [i.nlks]
  2169                              <1> 		; incb i.nlks / add 1 to its number of links
  2170 00003B2D E8F50E0000          <1> 	call	setimod
  2171                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2172 00003B32 E9F0F6FFFF          <1> 	jmp	sysret
  2173                              <1> 
  2174                              <1> isdir:
  2175                              <1> 	; 03/02/2022
  2176                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2177                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2178                              <1> 	;
  2179                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2180                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2181                              <1> 	;  called by syslink and sysunlink to make sure directories
  2182                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2183                              <1> 	; 'isdir' does not bother checking. The current i-node
  2184                              <1> 	;  is not disturbed.			
  2185                              <1> 	;		
  2186                              <1> 	; INPUTS ->
  2187                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2188                              <1> 	;    u.uid - user id
  2189                              <1> 	; OUTPUTS ->
  2190                              <1> 	;    r1 - contains current i-number upon exit
  2191                              <1> 	;    	 (current i-node back in core) 
  2192                              <1> 	;	
  2193                              <1> 	; ((AX = R1))
  2194                              <1> 	;
  2195                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2196                              <1> 	;
  2197                              <1> 
  2198                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2199                              <1> 	; / there is an error unless super user made the call
  2200                              <1> 	
  2201 00003B37 803D[56660000]00    <1> 	cmp	byte [u.uid], 0 
  2202                              <1> 		; tstb u.uid / super user
  2203 00003B3E 762B                <1> 	jna	short isdir1
  2204                              <1> 		; beq 1f / yes, don't care
  2205 00003B40 66FF35[F0650000]    <1> 	push	word [ii]
  2206                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2207 00003B47 E8D10D0000          <1> 	call	iget
  2208                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2209                              <1> 	; 03/02/2022
  2210 00003B4C F605[05630000]40    <1> 	test	byte [i.flgs+1], 40h
  2211                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2212                              <1> 		; bit $40000,i.flgs / is it a directory
  2213                              <1> 	;jnz	error
  2214                              <1> 		; bne error9 / yes, error
  2215 00003B53 740F                <1> 	jz	short isdir0
  2216 00003B55 C705[5F660000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2216 00003B5D 0000                <1>
  2217                              <1> 				; 'permission denied !' error
  2218                              <1> 	;pop	ax
  2219 00003B5F E9A3F6FFFF          <1> 	jmp	error	
  2220                              <1> isdir0:	
  2221 00003B64 6658                <1> 	pop	ax
  2222                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2223 00003B66 E8B20D0000          <1> 	call	iget
  2224                              <1> 		; jsr r0,iget / get it back in
  2225                              <1> isdir1: ; 1:
  2226 00003B6B C3                  <1> 	retn
  2227                              <1> 		; rts r0
  2228                              <1> 
  2229                              <1> sysunlink:
  2230                              <1> 	; 03/02/2022
  2231                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2232                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2233                              <1> 	;
  2234                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2235                              <1> 	; name from its directory. If this entry was the last link
  2236                              <1> 	; to the file, the contents of the file are freed and the
  2237                              <1> 	; file is destroyed. If, however, the file was open in any
  2238                              <1> 	; process, the actual destruction is delayed until it is 
  2239                              <1> 	; closed, even though the directory entry has disappeared.
  2240                              <1> 	; 
  2241                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2242                              <1> 	; does not exist or that its directory can not be written.
  2243                              <1> 	; Write permission is not required on the file itself.
  2244                              <1> 	; It is also illegal to unlink a directory (except for
  2245                              <1> 	; the superuser).
  2246                              <1> 	;
  2247                              <1> 	; Calling sequence:
  2248                              <1> 	;	sysunlink; name
  2249                              <1> 	; Arguments:
  2250                              <1> 	;	name - name of directory entry to be removed 
  2251                              <1> 	; Inputs: -
  2252                              <1> 	; Outputs: -
  2253                              <1> 	; ...............................................................
  2254                              <1> 	;				
  2255                              <1> 	; Retro UNIX 8086 v1 modification:
  2256                              <1> 	;	 The user/application program puts address of the name
  2257                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2258                              <1> 
  2259                              <1> 	; / name - remove link name
  2260 00003B6C 891D[28660000]      <1> 	mov	[u.namep], ebx
  2261                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2262 00003B72 E891050000          <1> 	call	namei
  2263                              <1> 		; jsr r0,namei / find the i-number associated 
  2264                              <1> 			     ; / with the path name
  2265                              <1> 	;jc	error
  2266                              <1> 		; br error9 / not found
  2267 00003B77 730F                <1> 	jnc	short sysunlink1
  2268                              <1> 	; 'file not found !' error
  2269 00003B79 C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2269 00003B81 0000                <1>
  2270 00003B83 E97FF6FFFF          <1> 	jmp	error
  2271                              <1> sysunlink1:
  2272                              <1> 	; 03/02/2022
  2273 00003B88 50                  <1> 	push	eax
  2274                              <1> 	;push	ax
  2275                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2276 00003B89 E8A9FFFFFF          <1> 	call	isdir
  2277                              <1> 		; jsr r0,isdir / is it a directory
  2278                              <1> 	;xor 	ax, ax
  2279                              <1> 	; 03/02/2022
  2280 00003B8E 31C0                <1> 	xor	eax, eax
  2281 00003B90 66A3[42660000]      <1> 	mov	[u.dirbuf], ax ; 0
  2282                              <1> 		; clr u.dirbuf / no, clear the location that will
  2283                              <1> 			   ; / get written into the i-number portion
  2284                              <1> 			 ; / of the entry
  2285 00003B96 832D[2C660000]0A    <1> 	sub	dword [u.off], 10
  2286                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2287 00003B9D E865000000          <1> 	call	wdir
  2288                              <1> 		; jsr r0,wdir / free the directory entry
  2289                              <1> 	; 03/02/2022
  2290 00003BA2 58                  <1> 	pop	eax
  2291                              <1> 	;pop	ax
  2292                              <1> 		; mov (sp)+,r1 / get i-number back
  2293 00003BA3 E8750D0000          <1> 	call	iget
  2294                              <1> 		; jsr r0,iget / get i-node
  2295 00003BA8 E87A0E0000          <1> 	call	setimod
  2296                              <1> 		; jsr r0,setimod / set modified flag
  2297 00003BAD FE0D[06630000]      <1> 	dec	byte [i.nlks]
  2298                              <1> 		; decb i.nlks / decrement the number of links
  2299                              <1> 	;jnz	sysret
  2300                              <1> 		; bgt sysret9 / if this was not the last link
  2301                              <1> 			    ; / to file return
  2302                              <1> 	; 03/02/2022
  2303 00003BB3 7505                <1> 	jnz	short sysunlink2
  2304                              <1> 	; AX = r1 = i-number
  2305 00003BB5 E8B8090000          <1> 	call	anyi
  2306                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2307                              <1> 			 ; / Then free contents of file and destroy it.
  2308                              <1> sysunlink2:
  2309 00003BBA E968F6FFFF          <1> 	jmp	sysret
  2310                              <1> 		; br sysret9
  2311                              <1> 
  2312                              <1> mkdir:
  2313                              <1> 	; 03/02/2022
  2314                              <1> 	; 12/10/2015
  2315                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2316                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2317                              <1> 	;
  2318                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2319                              <1> 	; by u.namep into the current directory.
  2320                              <1> 	;
  2321                              <1> 	; INPUTS ->
  2322                              <1> 	;    u.namep - points to a file name 
  2323                              <1> 	;	           that is about to be a directory entry.
  2324                              <1> 	;    ii - current directory's i-number.	
  2325                              <1> 	; OUTPUTS ->
  2326                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2327                              <1> 	;    u.off - points to entry to be filled 
  2328                              <1> 	;	     in the current directory		
  2329                              <1> 	;    u.base - points to start of u.dirbuf.
  2330                              <1> 	;    r1 - contains i-number of current directory 
  2331                              <1> 	;	
  2332                              <1> 	; ((AX = R1)) output
  2333                              <1> 	;
  2334                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2335                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2336                              <1> 	;
  2337                              <1> 
  2338                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2339 00003BBF 31C0                <1> 	xor 	eax, eax
  2340 00003BC1 BF[44660000]        <1>         mov     edi, u.dirbuf+2
  2341 00003BC6 89FE                <1> 	mov	esi, edi
  2342 00003BC8 AB                  <1> 	stosd
  2343 00003BC9 AB                  <1> 	stosd
  2344                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2345 00003BCA 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2346                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2347                              <1> 	;mov 	ebp, [u.namep]
  2348 00003BCC E8B9060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2349                              <1> 		; esi = physical address (page start + offset)
  2350                              <1> 		; ecx = byte count in the page (1 - 4096)
  2351                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2352                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2353                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2354                              <1> mkdir_1: ; 1: 
  2355 00003BD1 45                  <1> 	inc	ebp ; 12/10/2015
  2356                              <1> 	;
  2357                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2358                              <1> 	 ; 01/08/2013
  2359 00003BD2 AC                  <1> 	lodsb
  2360                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2361 00003BD3 20C0                <1> 	and 	al, al
  2362 00003BD5 7426                <1> 	jz 	short mkdir_3 	  
  2363                              <1> 		; beq 1f / if null, done
  2364 00003BD7 3C2F                <1> 	cmp	al, '/'
  2365                              <1> 		; cmp r1,$'/ / is it a "/"?
  2366 00003BD9 7413                <1> 	je	short mkdir_err
  2367                              <1> 	;je	error
  2368                              <1> 		; beq error9 / yes, error
  2369                              <1> 	; 03/02/2022
  2370 00003BDB 49                  <1> 	dec	ecx
  2371                              <1> 	; 12/10/2015
  2372                              <1> 	;dec	cx
  2373 00003BDC 7505                <1> 	jnz	short mkdir_2
  2374                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2375 00003BDE E8AD060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2376                              <1> 		; esi = physical address (page start + offset)
  2377                              <1> 		; ecx = byte count in the page
  2378                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2379                              <1> mkdir_2:
  2380 00003BE3 81FF[4C660000]      <1> 	cmp     edi, u.dirbuf+10
  2381                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2382                              <1> 				     ; / a char?
  2383 00003BE9 74E6                <1> 	je	short mkdir_1
  2384                              <1> 		; beq 1b / yes, go back
  2385 00003BEB AA                  <1> 	stosb
  2386                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2387 00003BEC EBE3                <1> 	jmp 	short mkdir_1
  2388                              <1> 		; br 1b / get next char
  2389                              <1> mkdir_err:
  2390                              <1> 	; 17/06/2015
  2391 00003BEE C705[5F660000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2391 00003BF6 0000                <1>
  2392 00003BF8 E90AF6FFFF          <1> 	jmp	error
  2393                              <1> mkdir_3: ; 1:
  2394 00003BFD A1[24660000]        <1> 	mov	eax, [u.dirp]
  2395 00003C02 A3[2C660000]        <1> 	mov	[u.off], eax
  2396                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2397                              <1> 				 ; / slot to u.off
  2398                              <1> wdir: 	; 03/02/2022
  2399                              <1> 	; 29/04/2013
  2400 00003C07 C705[30660000]-     <1>         mov     dword [u.base], u.dirbuf
  2400 00003C0D [42660000]          <1>
  2401                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2402 00003C11 C705[34660000]0A00- <1>         mov     dword [u.count], 10
  2402 00003C19 0000                <1>
  2403                              <1> 		; mov $10.,u.count / u.count = 10
  2404 00003C1B 66A1[F0650000]      <1> 	mov	ax, [ii] 
  2405                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2406 00003C21 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2407 00003C23 E8C90D0000          <1> 	call 	access
  2408                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2409                              <1> 				 ; / for writing
  2410                              <1> 	; AX = i-number of current directory
  2411                              <1> 	; 01/08/2013
  2412 00003C28 FE05[71660000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2413                              <1> 	;call	writei
  2414                              <1> 	;	; jsr r0,writei / write into directory
  2415                              <1> 	;retn	
  2416                              <1> 	;	; rts r0
  2417                              <1> 	; 03/02/2022
  2418 00003C2E E9AC100000          <1> 	jmp	writei
  2419                              <1> 
  2420                              <1> sysexec:
  2421                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2422                              <1> 	; 03/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18)
  2423                              <1> 	; 23/10/2015
  2424                              <1> 	; 19/10/2015
  2425                              <1> 	; 10/10/2015, 18/10/2015
  2426                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2427                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2428                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2429                              <1> 	; 24/06/2015, 25/06/2015
  2430                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2431                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2432                              <1> 	;
  2433                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2434                              <1> 	; pointed to by 'name' in the sysexec call. 
  2435                              <1> 	; 'sysexec' performs the following operations:
  2436                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2437                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2438                              <1> 	;    3. sets trap vectors to system routines.
  2439                              <1> 	;    4. loads arguments to be passed to executing file into
  2440                              <1> 	;	highest locations of user's core
  2441                              <1> 	;    5. puts pointers to arguments in locations immediately
  2442                              <1> 	;	following arguments.
  2443                              <1> 	;    6.	saves number of arguments in next location.
  2444                              <1> 	;    7. intializes user's stack area so that all registers
  2445                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2446                              <1> 	;	to core when 'sysret' restores registers 
  2447                              <1> 	;	and does an rti.
  2448                              <1> 	;    8. inializes u.r0 and u.sp
  2449                              <1> 	;    9. zeros user's core down to u.r0
  2450                              <1> 	;   10.	reads executable file from storage device into core
  2451                              <1> 	;	starting at location 'core'.
  2452                              <1> 	;   11.	sets u.break to point to end of user's code with
  2453                              <1> 	;	data area appended.
  2454                              <1> 	;   12.	calls 'sysret' which returns control at location
  2455                              <1> 	;	'core' via 'rti' instruction. 		  		
  2456                              <1> 	;
  2457                              <1> 	; Calling sequence:
  2458                              <1> 	;	sysexec; namep; argp
  2459                              <1> 	; Arguments:
  2460                              <1> 	;	namep - points to pathname of file to be executed
  2461                              <1> 	;	argp  - address of table of argument pointers
  2462                              <1> 	;	argp1... argpn - table of argument pointers
  2463                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2464                              <1> 	; Inputs: (arguments)
  2465                              <1> 	; Outputs: -	
  2466                              <1> 	; ...............................................................
  2467                              <1> 	;
  2468                              <1> 	; Retro UNIX 386 v1 modification: 
  2469                              <1> 	;	User application runs in it's own virtual space 
  2470                              <1> 	;	which is izolated from kernel memory (and other
  2471                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2472                              <1> 	;	privilige mode. Virtual start address is always 0.
  2473                              <1> 	;	User's core memory starts at linear address 400000h
  2474                              <1> 	;	(the end of the 1st 4MB).
  2475                              <1> 	;
  2476                              <1> 	; Retro UNIX 8086 v1 modification: 
  2477                              <1> 	;	user/application segment and system/kernel segment
  2478                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2479                              <1> 	;	are different (user's registers are saved to 
  2480                              <1> 	;	and then restored from system's stack.)
  2481                              <1> 	;
  2482                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2483                              <1> 	;	      arguments which were in these registers;
  2484                              <1> 	;	      but, it returns by putting the 1st argument
  2485                              <1> 	;	      in 'u.namep' and the 2nd argument
  2486                              <1> 	;	      on top of stack. (1st argument is offset of the
  2487                              <1> 	;	      file/path name in the user's program segment.)		 	
  2488                              <1> 	
  2489                              <1> 	;call	arg2
  2490                              <1> 	; * name - 'u.namep' points to address of file/path name
  2491                              <1> 	;          in the user's program segment ('u.segmnt')
  2492                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2493                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2494                              <1> 	;          which is on top of stack.
  2495                              <1> 	;
  2496                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2497                              <1> 
  2498                              <1> 	; 23/06/2015 (32 bit modifications)
  2499                              <1> 
  2500 00003C33 891D[28660000]      <1> 	mov	[u.namep], ebx ; argument 1
  2501                              <1>         ; 18/10/2015
  2502 00003C39 890D[88660000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2503 00003C3F E8C4040000          <1> 	call	namei
  2504                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2505                              <1> 			     ; / named in sysexec call in r1
  2506                              <1> 	;jc	error
  2507                              <1> 		; br error9
  2508 00003C44 731E                <1> 	jnc	short sysexec_0
  2509                              <1> 	;
  2510                              <1> 	; 'file not found !' error
  2511 00003C46 C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2511 00003C4E 0000                <1>
  2512 00003C50 E9B2F5FFFF          <1> 	jmp	error 
  2513                              <1> sysexec_not_exf:
  2514                              <1> 	; 'not executable file !' error
  2515 00003C55 C705[5F660000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2515 00003C5D 0000                <1>
  2516 00003C5F E9A3F5FFFF          <1> 	jmp	error 
  2517                              <1> sysexec_0:
  2518 00003C64 E8B40C0000          <1> 	call	iget
  2519                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2520                              <1> 	; 03/02/2022
  2521 00003C69 F605[04630000]10    <1> 	test	byte [i.flgs], 10h
  2522                              <1>         ;test	word [i.flgs], 10h
  2523                              <1> 		; bit $20,i.flgs / is file executable
  2524 00003C70 74E3                <1> 	jz	short sysexec_not_exf
  2525                              <1> 	;jz	error
  2526                              <1> 		; beq error9
  2527                              <1> 	;;
  2528 00003C72 E800150000          <1> 	call	iopen
  2529                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2530                              <1> 			     ; / given in r1 (opens file)
  2531                              <1> 	; AX = i-number of the file
  2532                              <1> 	; 03/02/2022
  2533 00003C77 F605[04630000]20    <1> 	test	byte [i.flgs], 20h
  2534                              <1> 	;test	word [i.flgs], 20h
  2535                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2536 00003C7E 7415                <1> 	jz	short sysexec_1
  2537                              <1> 		; beq 1f
  2538 00003C80 803D[56660000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2539                              <1> 		; tstb u.uid / test user id
  2540 00003C87 760C                <1> 	jna	short sysexec_1
  2541                              <1> 		; beq 1f / super user
  2542 00003C89 8A0D[07630000]      <1> 	mov	cl, [i.uid]
  2543 00003C8F 880D[56660000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2544                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2545                              <1> 				 ; / as process user id
  2546                              <1> sysexec_1:
  2547                              <1> 	; 03/02/2022
  2548                              <1> 	; 18/10/2215
  2549                              <1> 	; 10/10/2015
  2550                              <1> 	; 21/07/2015, 24/07/2015
  2551                              <1> 	; 24/06/2015, 25/06/2015
  2552                              <1>         ; Moving arguments to the end of [u.upage]
  2553                              <1> 	; (by regarding page borders in user's memory space)
  2554                              <1> 	;
  2555                              <1> 	; 10/10/2015
  2556                              <1> 	; 21/07/2015
  2557 00003C95 89E5                <1> 	mov	ebp, esp ; (**)
  2558                              <1> 	; 18/10/2015
  2559 00003C97 89EF                <1> 	mov 	edi, ebp
  2560 00003C99 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2561                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2562 00003C9E 29CF                <1> 	sub	edi, ecx
  2563 00003CA0 89FC                <1> 	mov	esp, edi
  2564 00003CA2 31C0                <1> 	xor	eax, eax
  2565 00003CA4 A3[38660000]        <1> 	mov 	[u.nread], eax ; 0
  2566                              <1> 	; 03/02/2022
  2567                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2568                              <1> 	; may leave it with any value after an error))
  2569                              <1> 	;mov	[argc], ax
  2570 00003CA9 A2[86660000]        <1> 	mov	[argc], al ; 0
  2571                              <1> 	;
  2572 00003CAE 49                  <1> 	dec	ecx ; 256 - 1
  2573 00003CAF 890D[34660000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2574                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2575                              <1> sysexec_2:
  2576 00003CB5 8B35[88660000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2577 00003CBB E864020000          <1> 	call	get_argp
  2578                              <1> 	;mov	ecx, 4 
  2579                              <1> 	; 03/02/2022
  2580 00003CC0 31C9                <1> 	xor	ecx, ecx
  2581 00003CC2 B104                <1> 	mov	cl, 4
  2582                              <1> sysexec_3:
  2583 00003CC4 21C0                <1> 	and	eax, eax
  2584 00003CC6 7456                <1> 	jz	short sysexec_6
  2585                              <1> 	; 18/10/2015
  2586 00003CC8 010D[88660000]      <1> 	add	[argv], ecx ; 4
  2587 00003CCE 66FF05[86660000]    <1> 	inc	word [argc]
  2588                              <1> 	;
  2589 00003CD5 A3[30660000]        <1> 	mov	[u.base], eax
  2590                              <1>  	; 23/10/2015
  2591 00003CDA 66C705[6F660000]00- <1> 	mov	word [u.pcount], 0
  2591 00003CE2 00                  <1>
  2592                              <1> sysexec_4:
  2593 00003CE3 E821120000          <1> 	call	cpass ; get a character from user's core memory
  2594 00003CE8 750B                <1>         jnz	short sysexec_5
  2595                              <1> 		; (max. 255 chars + null)
  2596                              <1> 	; 18/10/2015
  2597 00003CEA 28C0                <1> 	sub 	al, al
  2598 00003CEC AA                  <1> 	stosb
  2599 00003CED FF05[38660000]      <1> 	inc	dword [u.nread]
  2600 00003CF3 EB29                <1> 	jmp	short sysexec_6
  2601                              <1> sysexec_5:
  2602 00003CF5 AA                  <1> 	stosb
  2603 00003CF6 20C0                <1> 	and 	al, al
  2604 00003CF8 75E9                <1> 	jnz	short sysexec_4
  2605                              <1> 	;mov	ecx, 4
  2606                              <1> 	; 03/02/2022
  2607 00003CFA 29C9                <1> 	sub	ecx, ecx
  2608 00003CFC B104                <1> 	mov	cl, 4
  2609                              <1> 	;cmp	[ncount], ecx ; 4
  2610                              <1> 	; 03/02/2022
  2611 00003CFE 66390D[84660000]    <1> 	cmp	[ncount], cx ; 4
  2612 00003D05 72AE                <1> 	jb	short sysexec_2
  2613 00003D07 8B35[80660000]      <1> 	mov	esi, [nbase]
  2614 00003D0D 010D[80660000]      <1> 	add	[nbase], ecx ; 4	
  2615 00003D13 66290D[84660000]    <1> 	sub	[ncount], cx 
  2616 00003D1A 8B06                <1> 	mov	eax, [esi]
  2617 00003D1C EBA6                <1> 	jmp	short sysexec_3
  2618                              <1> sysexec_6:
  2619                              <1> 	; 18/10/2015
  2620                              <1> 	; argument list transfer from user's core memory to
  2621                              <1> 	; kernel stack frame is OK here.
  2622                              <1> 	; [u.nread] = ; argument list length
  2623                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2624                              <1> 	;
  2625                              <1> 	; 18/10/2015
  2626                              <1>         ; 21/07/2015, 24/07/2015
  2627                              <1> 	; 25/06/2015, 02/07/2015
  2628                              <1> 	; 23/06/2015, 24/06/2015
  2629                              <1> 	;
  2630 00003D1E 8B1D[67660000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2631 00003D24 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2632 00003D26 740A                <1> 	jz	short sysexec_7
  2633 00003D28 A1[63660000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2634 00003D2D E8FEE8FFFF          <1> 	call	deallocate_page_dir
  2635                              <1> sysexec_7:
  2636 00003D32 E82EE8FFFF          <1> 	call	make_page_dir
  2637                              <1> 	;jc	short sysexec_14
  2638                              <1> 	;jc	panic  ; allocation error 
  2639                              <1> 		       ; after a deallocation would be nonsence !?
  2640                              <1> 	; 03/02/2022
  2641 00003D37 7243                <1> 	jc	short sysexec_panic
  2642                              <1> 
  2643                              <1> 	; 24/07/2015
  2644                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2645                              <1> 	;     of the user's page directory
  2646                              <1> 	;     (It is needed for interrupts!)
  2647                              <1> 	; 18/10/2015
  2648 00003D39 8B15[48620000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2649 00003D3F 8B02                <1> 	mov	eax, [edx] ; physical address of
  2650                              <1> 			   ; kernel's first page table (1st 4 MB)
  2651                              <1> 			   ; (PDE 0 of kernel's page directory)
  2652 00003D41 8B15[63660000]      <1> 	mov 	edx, [u.pgdir]
  2653 00003D47 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2654                              <1> 	;
  2655                              <1> 	; 20/07/2015
  2656 00003D49 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2657                              <1> 	; 18/10/2015
  2658 00003D4E BE[78660000]        <1> 	mov	esi, pcore ; physical start address
  2659                              <1> sysexec_8:	
  2660 00003D53 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2661 00003D58 E826E8FFFF          <1> 	call	make_page_table
  2662                              <1> 	;jc	panic
  2663                              <1> 	; 03/02/2022
  2664 00003D5D 721D                <1> 	jc	short sysexec_panic
  2665                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2666 00003D5F E82DE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2667                              <1> 	;jc	panic
  2668                              <1> 	; 03/02/2022
  2669 00003D64 7216                <1> 	jc	short sysexec_panic
  2670                              <1> 	;
  2671 00003D66 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2672                              <1> 	; ebx = virtual address (24/07/2015)
  2673                              <1> 	; 03/02/2022
  2674                              <1> 	;call 	add_to_swap_queue
  2675                              <1> 	; 18/10/2015
  2676 00003D68 81FE[7C660000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2677 00003D6E 7411                <1> 	je	short sysexec_9 ; yes
  2678 00003D70 BE[7C660000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2679                              <1> 	; 20/07/2015
  2680 00003D75 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2681                              <1> 	; ebx = virtual end address + segment base address - 4K
  2682 00003D7A EBD7                <1>         jmp     short sysexec_8
  2683                              <1> 
  2684                              <1> sysexec_panic:
  2685                              <1> 	; 03/02/2022
  2686 00003D7C E945EDFFFF          <1> 	jmp	panic
  2687                              <1> 
  2688                              <1> sysexec_9:
  2689                              <1> 	; 18/10/2015
  2690                              <1> 	; 26/08/2015
  2691                              <1> 	; 25/06/2015
  2692                              <1> 	; move arguments from kernel stack to [ecore]
  2693                              <1> 	; (argument list/line will be copied from kernel stack
  2694                              <1> 	; frame to the last (stack) page of user's core memory)
  2695                              <1> 	; 18/10/2015
  2696 00003D81 8B3D[7C660000]      <1> 	mov	edi, [ecore]
  2697 00003D87 81C700100000        <1> 	add	edi, PAGE_SIZE
  2698                              <1> 	;movzx	eax, word [argc]
  2699                              <1> 	; 03/02/2022
  2700 00003D8D 31C0                <1> 	xor	eax, eax
  2701 00003D8F A0[86660000]        <1> 	mov	al, [argc]
  2702 00003D94 08C0                <1> 	or	al, al
  2703                              <1> 	;or	eax, eax
  2704 00003D96 7509                <1> 	jnz	short sysexec_10
  2705 00003D98 89FB                <1> 	mov 	ebx, edi
  2706 00003D9A 83EB04              <1> 	sub	ebx, 4 
  2707 00003D9D 8903                <1> 	mov	[ebx], eax ; 0
  2708 00003D9F EB43                <1> 	jmp 	short sysexec_13
  2709                              <1> sysexec_10:
  2710 00003DA1 8B0D[38660000]      <1> 	mov	ecx, [u.nread]
  2711                              <1> 	;mov 	esi, [argv]
  2712 00003DA7 89E6                <1> 	mov	esi, esp ; start address of argument list
  2713 00003DA9 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2714                              <1> 	
  2715                              <1> 	;;;;
  2716                              <1> 	; 09/05/2022
  2717                              <1> 	; (move edi -backward- to dword boundary)
  2718                              <1> 	; ((this will prevent 'general protection fault' error
  2719                              <1> 	;  as result of a lodsd or dword move instruction
  2720                              <1> 	;  at the end of argument list))
  2721 00003DAB 83EF03              <1> 	sub	edi, 3
  2722 00003DAE 83E7FC              <1> 	and	edi, ~3 ; (*)
  2723                              <1> 	;;;
  2724                              <1> 
  2725 00003DB1 89C2                <1> 	mov	edx, eax
  2726                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2727 00003DB3 FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2728 00003DB5 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2729                              <1> 	; edx <= 128
  2730 00003DB8 89FB                <1> 	mov	ebx, edi
  2731                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2732                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2733 00003DBA 29D3                <1> 	sub 	ebx, edx
  2734 00003DBC 89FA                <1> 	mov	edx, edi
  2735 00003DBE F3A4                <1> 	rep	movsb
  2736 00003DC0 89D6                <1> 	mov 	esi, edx
  2737 00003DC2 89DF                <1> 	mov 	edi, ebx
  2738 00003DC4 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2739 00003DC9 2B15[7C660000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2740 00003DCF AB                  <1> 	stosd	; eax = argument count	
  2741                              <1> sysexec_11:
  2742 00003DD0 89F0                <1> 	mov	eax, esi
  2743 00003DD2 01D0                <1> 	add	eax, edx
  2744 00003DD4 AB                  <1> 	stosd  ; eax = virtual address
  2745 00003DD5 FE0D[86660000]      <1> 	dec	byte [argc]
  2746 00003DDB 7407                <1> 	jz	short sysexec_13
  2747                              <1> sysexec_12:
  2748 00003DDD AC                  <1> 	lodsb
  2749 00003DDE 20C0                <1> 	and	al, al
  2750 00003DE0 75FB                <1> 	jnz	short sysexec_12
  2751 00003DE2 EBEC                <1> 	jmp	short sysexec_11
  2752                              <1> 	;
  2753                              <1> 	; 1:
  2754                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2755                              <1> 			     ; / pointers to arguments to be passed
  2756                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2757                              <1> 			      ; / u.quit = 1 take quit
  2758                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2759                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2760                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2761                              <1> 			       ; / system routine
  2762                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2763                              <1> 			       ; / set to take system routine
  2764                              <1> 		; mov $sstack,sp / stack space used during swapping
  2765                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2766                              <1> 		; mov $ecore,r5 / r5 has end of core
  2767                              <1> 		; mov $core,r4 / r4 has start of users core
  2768                              <1> 		; mov r4,u.base / u.base has start of users core
  2769                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2770                              <1> 	; 1:
  2771                              <1> 		; tst (r2)+ / argument char = "nul"
  2772                              <1> 		; bne 1b
  2773                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2774                              <1> 			  ; / end of argument pointer list
  2775                              <1> 	; 1:
  2776                              <1> 	     ; / move arguments to bottom of users core
  2777                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2778                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2779                              <1> 			    ; / ptr list
  2780                              <1> 		; blo 1f / branch to 1f when all arguments
  2781                              <1> 		       ; / are moved
  2782                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2783                              <1> 	; 2:
  2784                              <1> 		; tstb (r3)+
  2785                              <1> 		; bne 2b / scan argument for \0 (nul)
  2786                              <1> 
  2787                              <1> 	; 2:
  2788                              <1> 		; movb -(r3),-(r5) / move argument char 
  2789                              <1> 				 ; / by char starting at "ecore"
  2790                              <1> 		; cmp r3,(r2) / moved all characters in 
  2791                              <1> 			    ; / this argument
  2792                              <1> 		; bhi 2b / branch 2b if not
  2793                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2794                              <1> 			     ; / r5 has pointer to nth arg
  2795                              <1> 		; br 1b / string
  2796                              <1> 	; 1:
  2797                              <1> 		; clrb -(r5)
  2798                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2799                              <1> 			 ; / last word of argument strings
  2800                              <1> 		; mov $core,r2
  2801                              <1> 	
  2802                              <1> 	; 1: / move argument pointers into core following 
  2803                              <1> 	      ; / argument strings
  2804                              <1> 		; cmp r2,r4
  2805                              <1> 		; bhis 1f / branch to 1f when all pointers
  2806                              <1> 			; / are moved
  2807                              <1> 		; mov (r2)+,-(r5)
  2808                              <1> 		; br 1b
  2809                              <1> 	; 1:
  2810                              <1> 		; sub $core,r4 / gives number of arguments *2
  2811                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2812                              <1> 		       ; / the number of args stored
  2813                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2814                              <1> 			     ; / of the argument pointers
  2815                              <1> sysexec_13:
  2816                              <1> 	; 19/10/2015
  2817                              <1> 	; 18/10/2015
  2818                              <1> 	; 29/07/2015
  2819                              <1> 	; 24/07/2015, 25/07/2015
  2820                              <1> 	; 25/06/2015, 20/07/2015
  2821                              <1> 	; 23/06/2015, 24/06/2015
  2822                              <1> 	;
  2823                              <1> 	; moving arguments to [ecore] is OK here..
  2824                              <1> 	; 18/10/2015
  2825 00003DE4 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2826                              <1> 	; ebx = beginning addres of argument list pointers
  2827                              <1> 	;	in user's stack
  2828                              <1> 	; 19/10/2015
  2829 00003DE6 2B1D[7C660000]      <1> 	sub 	ebx, [ecore]
  2830 00003DEC 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2831                              <1> 			; end of core - 4096 (last page)
  2832                              <1> 			; (virtual address)
  2833 00003DF2 891D[88660000]      <1> 	mov	[argv], ebx
  2834 00003DF8 891D[3C660000]      <1> 	mov	[u.break], ebx ; available user memory
  2835                              <1> 	;
  2836 00003DFE 29C0                <1> 	sub	eax, eax
  2837 00003E00 C705[34660000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2837 00003E08 0000                <1>
  2838                              <1> 		; mov $14,u.count
  2839 00003E0A C705[20660000]-     <1> 	mov	dword [u.fofp], u.off
  2839 00003E10 [2C660000]          <1>
  2840                              <1> 		; mov $u.off,u.fofp
  2841 00003E14 A3[2C660000]        <1> 	mov	[u.off], eax ; 0
  2842                              <1> 		; clr u.off / set offset in file to be read to zero
  2843                              <1> 	; 25/07/2015
  2844 00003E19 A3[30660000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2845                              <1> 	; 25/06/2015 
  2846 00003E1E 66A1[F0650000]      <1> 	mov	ax, [ii]
  2847                              <1> 	; AX = i-number of the executable file
  2848 00003E24 E8C80C0000          <1> 	call	readi
  2849                              <1> 		; jsr r0,readi / read in first six words of 
  2850                              <1> 			; / user's file, starting at $core
  2851                              <1> 		; mov sp,r5 / put users stack address in r5
  2852                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2853                              <1> 				; / from r5 (leaves number of words
  2854                              <1> 				; / less 26 available for
  2855                              <1> 			     	; / program in user core
  2856                              <1> 		; mov r5,u.count /
  2857                              <1> 	; 25/06/2015
  2858 00003E29 8B0D[3C660000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2859 00003E2F 890D[34660000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2860                              <1> 	;
  2861 00003E35 8B0D[38660000]      <1> 	mov	ecx, [u.nread]
  2862 00003E3B 890D[3C660000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2863 00003E41 80F920              <1> 	cmp	cl, 32
  2864 00003E44 7540                <1>         jne     short sysexec_15
  2865                              <1> 	;:
  2866                              <1> 	; 25/06/2015
  2867                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2868                              <1> 	; 18/10/2015
  2869 00003E46 8B35[78660000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2870                              <1> 		             ; (phys. start addr. of the exec. file)
  2871 00003E4C AD                  <1> 	lodsd
  2872 00003E4D 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2873 00003E51 7533                <1> 	jne	short sysexec_15
  2874                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2875                              <1> 			      ; / if file is standard a.out format
  2876                              <1> 		; bne 1f / branch, if not standard format
  2877 00003E53 AD                  <1> 	lodsd
  2878 00003E54 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2879 00003E56 AD                  <1> 	lodsd
  2880 00003E57 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2881                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2882                              <1> 		              ; / number of bytes in program text	
  2883                              <1> 		; sub $14,r5 / subtract 12
  2884 00003E59 89CB                <1> 	mov	ebx, ecx
  2885                              <1> 	;
  2886                              <1> 	; 25/06/2015
  2887                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2888                              <1> 	;	and SINGLIX operating systems (as code template).
  2889                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2890                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2891                              <1> 	;	Overrun is not possible for current version. 	
  2892                              <1> 	;
  2893 00003E5B AD                  <1> 	lodsd	
  2894 00003E5C 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2895 00003E5E 3B1D[34660000]      <1> 	cmp	ebx, [u.count]
  2896 00003E64 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2897                              <1> 	;
  2898                              <1> 	; 24/07/2015
  2899                              <1> 	; add bss section size to [u.break]
  2900 00003E66 0105[3C660000]      <1> 	add 	[u.break], eax
  2901                              <1> 	;
  2902 00003E6C 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2903                              <1> 	;cmp	ecx, [u.count]
  2904                              <1> 	;jnb	short sysexec_16
  2905                              <1> 		; cmp r5,u.count /
  2906                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2907 00003E6F 890D[34660000]      <1> 	mov	[u.count], ecx ; required read count
  2908                              <1> 		; mov r5,u.count
  2909                              <1> 	;
  2910 00003E75 EB2A                <1> 	jmp	short sysexec_16
  2911                              <1> 	;
  2912                              <1> sysexec_14:
  2913                              <1> 	; 23/06/2015
  2914                              <1> 	; insufficient (out of) memory
  2915 00003E77 C705[5F660000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2915 00003E7F 0000                <1>
  2916 00003E81 E981F3FFFF          <1> 	jmp	error
  2917                              <1> 	;
  2918                              <1> sysexec_15:
  2919                              <1> 	; 25/06/2015
  2920 00003E86 0FB715[08630000]    <1>         movzx   edx, word [i.size] ; file size
  2921 00003E8D 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2922 00003E8F 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2923 00003E91 01D1                <1> 	add	ecx, edx ; [i.size]
  2924 00003E93 3B0D[34660000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2925 00003E99 77DC                <1> 	ja	short sysexec_14
  2926 00003E9B 8915[34660000]      <1> 	mov	[u.count], edx
  2927                              <1> sysexec_16:
  2928 00003EA1 66A1[F0650000]      <1> 	mov	ax, [ii] ; i-number
  2929 00003EA7 E8450C0000          <1> 	call	readi
  2930                              <1> 		; add core+10,u.nread / add size of user data area 
  2931                              <1> 		                    ; / to u.nread
  2932                              <1> 		; br 2f
  2933                              <1> 	; 1:
  2934                              <1> 		; jsr r0,readi / read in rest of file
  2935                              <1> 	; 2:
  2936 00003EAC 8B0D[38660000]      <1> 	mov	ecx, [u.nread]
  2937 00003EB2 010D[3C660000]      <1> 	add	[u.break], ecx
  2938                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2939                              <1> 				    ; / user code
  2940                              <1> 		; add $core+14,u.break / plus data area
  2941                              <1> sysexec_17: ; 20/07/2015
  2942                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2943                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2944                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2945                              <1> 	;;mov	ax, [ii] ; i-number
  2946                              <1> 	;call	iclose
  2947                              <1> 	;	; jsr r0,iclose / does nothing
  2948 00003EB8 31C0                <1>         xor     eax, eax
  2949 00003EBA FEC0                <1> 	inc	al
  2950 00003EBC 66A3[4E660000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2951 00003EC2 66A3[50660000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2952                              <1> 	; 02/07/2015
  2953 00003EC8 833D[67660000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2954 00003ECF 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2955                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2956 00003ED1 8B15[48620000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2957 00003ED7 8915[67660000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2958                              <1> sysexec_18:
  2959                              <1> 	; 18/10/2015
  2960                              <1> 	; 05/08/2015
  2961                              <1> 	; 29/07/2015
  2962 00003EDD 8B2D[88660000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2963                              <1> 			    ; list pointers (argument count)
  2964 00003EE3 FA                  <1> 	cli
  2965 00003EE4 8B25[E4610000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2966                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2967                              <1> 			    ; for this process	 
  2968                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2969                              <1> 	;xor	eax, eax ; 0
  2970 00003EEA FEC8                <1> 	dec	al ; eax = 0
  2971 00003EEC 66BA2300            <1> 	mov	dx, UDATA
  2972 00003EF0 6652                <1> 	push	dx  ; user's stack segment
  2973 00003EF2 55                  <1> 	push	ebp ; user's stack pointer
  2974                              <1> 		    ; (points to number of arguments)
  2975 00003EF3 FB                  <1> 	sti
  2976 00003EF4 9C                  <1> 	pushfd	; EFLAGS
  2977                              <1> 		; Set IF for enabling interrupts in user mode	
  2978                              <1> 	;or	dword [esp], 200h 
  2979                              <1> 	;
  2980                              <1> 	;mov	bx, UCODE
  2981                              <1> 	;push	bx ; user's code segment
  2982 00003EF5 6A1B                <1> 	push	UCODE
  2983                              <1> 	;push	0
  2984 00003EF7 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2985                              <1> 		; clr -(r5) / popped into ps when rti in 
  2986                              <1> 			  ; / sysrele is executed
  2987                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2988                              <1> 		                ; / in sysrele is executed
  2989                              <1> 		;mov r5,0f / load second copyz argument
  2990                              <1> 		;tst -(r5) / decrement r5
  2991 00003EF8 8925[08660000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2992                              <1> 	; 05/08/2015
  2993                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2994                              <1> 	; ('push dx' would cause to general protection fault, 
  2995                              <1> 	; after 'pop ds' etc.)
  2996                              <1> 	;
  2997                              <1> 	;; push dx ; ds (UDATA)
  2998                              <1> 	;; push dx ; es (UDATA)
  2999                              <1> 	;; push dx ; fs (UDATA)
  3000                              <1> 	;; push dx ; gs (UDATA)
  3001                              <1> 	;
  3002                              <1> 	; This is a trick to prevent general protection fault
  3003                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3004 00003EFE 8EC2                <1> 	mov 	es, dx ; UDATA
  3005 00003F00 06                  <1> 	push 	es ; ds (UDATA)
  3006 00003F01 06                  <1> 	push 	es ; es (UDATA)
  3007 00003F02 06                  <1> 	push 	es ; fs (UDATA)
  3008 00003F03 06                  <1> 	push	es ; gs (UDATA)
  3009 00003F04 66BA1000            <1> 	mov	dx, KDATA
  3010 00003F08 8EC2                <1> 	mov	es, dx
  3011                              <1> 	;
  3012                              <1> 	;; pushad simulation
  3013 00003F0A 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3014 00003F0C 50                  <1> 	push	eax ; eax (0)
  3015 00003F0D 50                  <1> 	push	eax ; ecx (0)
  3016 00003F0E 50                  <1> 	push	eax ; edx (0)
  3017 00003F0F 50                  <1> 	push	eax ; ebx (0)
  3018 00003F10 55                  <1> 	push	ebp ; esp before pushad
  3019 00003F11 50                  <1> 	push	eax ; ebp (0)
  3020 00003F12 50                  <1> 	push	eax ; esi (0)		
  3021 00003F13 50                  <1> 	push	eax ; edi (0)	
  3022                              <1> 	;
  3023 00003F14 A3[10660000]        <1> 	mov	[u.r0], eax ; eax = 0
  3024 00003F19 8925[0C660000]      <1> 	mov	[u.usp], esp
  3025                              <1> 		; mov r5,u.r0 /
  3026                              <1> 		; sub $16.,r5 / skip 8 words
  3027                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3028                              <1> 		;             / effectively zeroes all regs
  3029                              <1> 			    ; / when sysrele is executed
  3030                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3031                              <1> 		; clr u.break
  3032                              <1> 		; mov r5,sp / point sp to user's stack
  3033                              <1> 	;
  3034 00003F1F E905F3FFFF          <1> 	jmp	sysret0
  3035                              <1> 	;jmp	sysret
  3036                              <1> 		; br sysret3 / return to core image at $core
  3037                              <1> 
  3038                              <1> get_argp:
  3039                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  3040                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3041                              <1> 	; 18/10/2015 (nbase, ncount)
  3042                              <1> 	; 21/07/2015
  3043                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3044                              <1> 	; Get (virtual) address of argument from user's core memory
  3045                              <1> 	;
  3046                              <1> 	; INPUT:
  3047                              <1> 	;	esi = virtual address of argument pointer
  3048                              <1> 	; OUTPUT:
  3049                              <1> 	;	eax = virtual address of argument
  3050                              <1> 	;
  3051                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3052                              <1> 	;
  3053 00003F24 833D[67660000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3054                              <1> 				    ; (the caller is kernel)
  3055                              <1>         ;jna	short get_argpk
  3056                              <1> 	; 03/02/2022
  3057 00003F2B 7719                <1> 	ja	short get_argp5
  3058                              <1> get_argpk:
  3059                              <1> 	; Argument is in kernel's memory space
  3060 00003F2D 66C705[84660000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3060 00003F35 10                  <1>
  3061 00003F36 8935[80660000]      <1> 	mov	[nbase], esi
  3062 00003F3C 8305[80660000]04    <1> 	add	dword [nbase], 4
  3063 00003F43 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3064 00003F45 C3                  <1> 	retn
  3065                              <1> get_argp5:
  3066 00003F46 89F3                <1>      	mov	ebx, esi
  3067 00003F48 E89FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3068 00003F4D 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  3069 00003F4F A3[80660000]        <1> 	mov 	[nbase], eax ; physical address	
  3070 00003F54 66890D[84660000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3071 00003F5B B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3072                              <1> 	;cmp	cx, ax ; 4
  3073                              <1> 	; 03/02/2022
  3074 00003F60 39C1                <1> 	cmp	ecx, eax
  3075 00003F62 734C                <1> 	jnb	short get_argp2
  3076 00003F64 89F3                <1> 	mov	ebx, esi
  3077 00003F66 01CB                <1> 	add	ebx, ecx
  3078 00003F68 E87FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3079 00003F6D 7237                <1> 	jc	short get_argp_err
  3080                              <1> 	;push	esi
  3081 00003F6F 89C6                <1> 	mov	esi, eax
  3082 00003F71 66870D[84660000]    <1> 	xchg	cx, [ncount]
  3083 00003F78 8735[80660000]      <1> 	xchg	esi, [nbase]
  3084 00003F7E B504                <1> 	mov	ch, 4
  3085 00003F80 28CD                <1> 	sub	ch, cl
  3086                              <1> get_argp0:
  3087 00003F82 AC                  <1> 	lodsb
  3088                              <1> 	;push	ax
  3089                              <1> 	; 03/02/2022
  3090 00003F83 50                  <1> 	push	eax
  3091 00003F84 FEC9                <1> 	dec	cl
  3092 00003F86 75FA                <1>         jnz     short get_argp0
  3093 00003F88 8B35[80660000]      <1> 	mov	esi, [nbase]
  3094                              <1> 	; 21/07/2015
  3095 00003F8E 0FB6C5              <1> 	movzx	eax, ch
  3096 00003F91 0105[80660000]      <1> 	add	[nbase], eax
  3097 00003F97 662905[84660000]    <1> 	sub	[ncount], ax
  3098                              <1> get_argp1:
  3099 00003F9E AC                  <1> 	lodsb
  3100 00003F9F FECD                <1> 	dec	ch
  3101 00003FA1 7423                <1>         jz      short get_argp3
  3102                              <1>         ;push	ax
  3103                              <1> 	; 03/02/2022
  3104 00003FA3 50                  <1> 	push	eax
  3105 00003FA4 EBF8                <1> 	jmp     short get_argp1
  3106                              <1> get_argp_err:
  3107 00003FA6 A3[5F660000]        <1> 	mov	[u.error], eax
  3108 00003FAB E957F2FFFF          <1> 	jmp	error
  3109                              <1> get_argp2:
  3110                              <1> 	; 21/07/2015
  3111                              <1> 	;mov	eax, 4
  3112 00003FB0 8B15[80660000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3113 00003FB6 0105[80660000]      <1> 	add	[nbase], eax
  3114 00003FBC 662905[84660000]    <1> 	sub	[ncount], ax
  3115                              <1> 	;
  3116 00003FC3 8B02                <1> 	mov	eax, [edx]
  3117 00003FC5 C3                  <1> 	retn
  3118                              <1> get_argp3:
  3119 00003FC6 B103                <1> 	mov	cl, 3
  3120                              <1> get_argp4:
  3121 00003FC8 C1E008              <1> 	shl	eax, 8
  3122                              <1> 	;pop	dx
  3123                              <1> 	; 03/02/2022
  3124 00003FCB 5A                  <1> 	pop	edx
  3125 00003FCC 88D0                <1> 	mov 	al, dl
  3126 00003FCE E2F8                <1>         loop    get_argp4
  3127                              <1> 	;pop	esi
  3128 00003FD0 C3                  <1> 	retn	
  3129                              <1> 
  3130                              <1> sysfstat:
  3131                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3132                              <1> 	;	([idev] return in eax)
  3133                              <1> 	;	0 = root device
  3134                              <1> 	;	1 = mounted device (>0)
  3135                              <1> 	; 03/02/2022
  3136                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3137                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3138                              <1> 	;
  3139                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3140                              <1> 	; on open files instead of files given by name. It puts the
  3141                              <1> 	; buffer address on the stack, gets the i-number and
  3142                              <1> 	; checks to see if the file is open for reading or writing.
  3143                              <1> 	; If the file is open for writing (i-number is negative)
  3144                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3145                              <1> 	; is made.	
  3146                              <1> 	;
  3147                              <1> 	; Calling sequence:
  3148                              <1> 	;	sysfstat; buf
  3149                              <1> 	; Arguments:
  3150                              <1> 	;	buf - buffer address
  3151                              <1> 	;
  3152                              <1> 	; Inputs: *u.r0 - file descriptor
  3153                              <1> 	; Outputs: buffer is loaded with file information
  3154                              <1> 	; ...............................................................
  3155                              <1> 	;				
  3156                              <1> 	; Retro UNIX 8086 v1 modification:
  3157                              <1> 	;       'sysfstat' system call has two arguments; so,
  3158                              <1> 	;	* 1st argument, file descriptor is in BX register
  3159                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3160                              <1> 
  3161                              <1> 	; / set status of open file
  3162                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3163 00003FD1 51                  <1> 	push	ecx
  3164                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3165                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3166                              <1> 		; jsr r0,getf / get the files i-number
  3167                              <1> 	; BX = file descriptor (file number)
  3168 00003FD2 E8FE000000          <1> 	call	getf1
  3169                              <1> 	; 03/02/2022
  3170 00003FD7 21C0                <1> 	and	eax, eax
  3171                              <1> 	;and	ax, ax ; i-number of the file
  3172                              <1> 		; tst	r1 / is it 0?
  3173                              <1> 	;jz	error
  3174                              <1> 		; beq error3 / yes, error
  3175 00003FD9 750F                <1> 	jnz	short sysfstat1
  3176 00003FDB C705[5F660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3176 00003FE3 0000                <1>
  3177 00003FE5 E91DF2FFFF          <1> 	jmp	error
  3178                              <1> sysfstat1:
  3179 00003FEA 80FC80              <1> 	cmp	ah, 80h
  3180 00003FED 7222                <1>         jb      short sysstat1
  3181                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3182 00003FEF 66F7D8              <1> 	neg	ax
  3183                              <1> 		; neg r1 / make it positive, then branch
  3184 00003FF2 EB1D                <1> 	jmp	short sysstat1
  3185                              <1> 		; br 1f / to 1f
  3186                              <1> sysstat:
  3187                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3188                              <1> 	;	([idev] return in eax)
  3189                              <1> 	;	0 = root device
  3190                              <1> 	;	1 = mounted device (>0)
  3191                              <1> 	; 03/02/2022
  3192                              <1> 	; 18/10/2015
  3193                              <1> 	; 07/10/2015
  3194                              <1> 	; 02/09/2015
  3195                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3196                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3197                              <1> 	;
  3198                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3199                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3200                              <1> 	; long and information about the file placed in it.	
  3201                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3202                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3203                              <1> 	; is then loaded and the results are given in the UNIX
  3204                              <1> 	; Programmers Manual sysstat (II).	
  3205                              <1> 	;
  3206                              <1> 	; Calling sequence:
  3207                              <1> 	;	sysstat; name; buf
  3208                              <1> 	; Arguments:
  3209                              <1> 	;	name - points to the name of the file
  3210                              <1> 	;	buf - address of a 34 bytes buffer
  3211                              <1> 	; Inputs: -
  3212                              <1> 	; Outputs: buffer is loaded with file information
  3213                              <1> 	; ...............................................................
  3214                              <1> 	;				
  3215                              <1> 	; Retro UNIX 8086 v1 modification: 
  3216                              <1> 	;       'sysstat' system call has two arguments; so,
  3217                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3218                              <1> 	;	to get sysstat system call arguments from the user;
  3219                              <1> 	;	* 1st argument, name is pointed to by BX register
  3220                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3221                              <1> 	;
  3222                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3223                              <1> 	;	      arguments which were in these registers;
  3224                              <1> 	;	      but, it returns by putting the 1st argument
  3225                              <1> 	;	      in 'u.namep' and the 2nd argument
  3226                              <1> 	;	      on top of stack. (1st argument is offset of the
  3227                              <1> 	;	      file/path name in the user's program segment.)		 	
  3228                              <1> 	
  3229                              <1> 	; / ; name of file; buffer - get files status
  3230                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3231 00003FF4 891D[28660000]      <1> 	mov	[u.namep], ebx
  3232 00003FFA 51                  <1> 	push	ecx
  3233 00003FFB E808010000          <1> 	call	namei
  3234                              <1> 		; jsr r0,namei / get the i-number for the file
  3235                              <1> 	;jc	error
  3236                              <1> 		; br error3 / no such file, error
  3237 00004000 730F                <1> 	jnc	short sysstat1
  3238                              <1> 	; pop 	ecx
  3239                              <1> sysstat_err0:
  3240                              <1> 	; 'file not found !' error
  3241 00004002 C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3241 0000400A 0000                <1>
  3242 0000400C E9F6F1FFFF          <1> 	jmp	error
  3243                              <1> 
  3244                              <1> ;statx: db 0
  3245                              <1> 
  3246                              <1> sysstat1: ; 1:
  3247 00004011 E807090000          <1> 	call	iget
  3248                              <1> 		; jsr r0,iget / get the i-node into core
  3249                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3250                              <1> 	; 02/09/2015
  3251 00004016 8F05[30660000]      <1> 	pop	dword [u.base]
  3252                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3253 0000401C E861000000          <1> 	call	sysstat_gpa ; get physical address
  3254 00004021 730A                <1> 	jnc 	short sysstat2
  3255                              <1> sysstat_err1:
  3256 00004023 A3[5F660000]        <1> 	mov	dword [u.error], eax ; error code
  3257 00004028 E9DAF1FFFF          <1> 	jmp	error
  3258                              <1> sysstat2:
  3259 0000402D A0[F0650000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3260 00004032 AA                  <1> 	stosb
  3261 00004033 FF05[30660000]      <1> 	inc 	dword [u.base]
  3262                              <1> 	;dec 	cx
  3263                              <1> 	; 03/02/2022
  3264 00004039 49                  <1> 	dec	ecx
  3265 0000403A 7505                <1> 	jnz	short sysstat3
  3266 0000403C E841000000          <1> 	call	sysstat_gpa
  3267                              <1> 	;jc	short sysstat_err1
  3268                              <1> sysstat3:
  3269 00004041 A0[F1650000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3270 00004046 AA                  <1> 	stosb
  3271                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3272 00004047 FF05[30660000]      <1> 	inc 	dword [u.base]
  3273                              <1> 	;;dec 	word [u.pcount]
  3274                              <1> 	;dec	cx
  3275                              <1> 	; 03/02/2022
  3276 0000404D 49                  <1> 	dec	ecx
  3277 0000404E 7505                <1> 	jnz	short sysstat4
  3278 00004050 E82D000000          <1> 	call	sysstat_gpa
  3279                              <1> 	;jc	short sysstat_err1	
  3280                              <1> sysstat4:
  3281 00004055 BE[04630000]        <1> 	mov	esi, inode
  3282                              <1> 		; mov $inode,r2 / r2 points to i-node
  3283                              <1> sysstat5: ; 1:
  3284 0000405A A4                  <1> 	movsb
  3285                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3286 0000405B FF05[30660000]      <1> 	inc 	dword [u.base]
  3287                              <1> 	;;dec 	word [u.pcount]
  3288                              <1> 	;dec	cx
  3289                              <1> 	; 03/02/2022
  3290 00004061 49                  <1> 	dec	ecx
  3291 00004062 7505                <1> 	jnz	short sysstat6
  3292 00004064 E819000000          <1> 	call	sysstat_gpa
  3293                              <1> 	;jc	short sysstat_err1
  3294                              <1> sysstat6:		
  3295 00004069 81FE[24630000]      <1> 	cmp	esi, inode + 32
  3296                              <1> 		; cmp r2,$inode+32 / done?
  3297 0000406F 75E9                <1> 	jne	short sysstat5
  3298                              <1> 		; bne 1b / no, go back
  3299                              <1> 
  3300                              <1> 	;;;
  3301                              <1> 	; 09/05/2022
  3302                              <1> 	;*** additional feature *** -retro unix only- 
  3303                              <1> 	;
  3304                              <1> 	; !! return device number -of current inode- in eax !!
  3305                              <1> 	;
  3306                              <1> 	; (modification reason/purpose:
  3307                              <1> 	; to improve 'pwd' command's pathname output/result
  3308                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3309                              <1> 	; error due to same inode numbers in root file system
  3310                              <1> 	; and mounted file system.)
  3311                              <1> 	;
  3312 00004071 29C0                <1> 	sub	eax, eax
  3313 00004073 A0[F2650000]        <1> 	mov	al, [idev] ; [cdev]
  3314 00004078 A3[10660000]        <1> 	mov	[u.r0], eax
  3315                              <1> 	;;;  
  3316                              <1> 
  3317 0000407D E9A5F1FFFF          <1> 	jmp	sysret
  3318                              <1> 		; br sysret3 / return through sysret
  3319                              <1> 	;
  3320                              <1> sysstat_gpa: ; get physical address of file status buffer
  3321                              <1> 	; 02/09/2015
  3322 00004082 8B1D[30660000]      <1> 	mov 	ebx, [u.base]
  3323                              <1> 	; 07/10/2015
  3324 00004088 E85FE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3325                              <1> 	;jc	short sysstat_gpa1
  3326 0000408D 7294                <1> 	jc	short sysstat_err1
  3327                              <1> 	; 18/10/2015
  3328 0000408F 89C7                <1> 	mov	edi, eax ; physical address
  3329                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3330                              <1> ;sysstat_gpa1:
  3331 00004091 C3                  <1> 	retn
  3332                              <1> 
  3333                              <1> fclose:
  3334                              <1> 	; 03/02/2022
  3335                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3336                              <1> 	;            (32 bit offset pointer modification)
  3337                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3338                              <1> 	;
  3339                              <1> 	; Given the file descriptor (index to the u.fp list)
  3340                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3341                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3342                              <1> 	; u.fp list is cleared. If all the processes that opened
  3343                              <1> 	; that file close it, then fsp etry is freed and the file
  3344                              <1> 	; is closed. If not a return is taken. 
  3345                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3346                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3347                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3348                              <1> 	; a check is made to see if the file is special.	
  3349                              <1> 	;
  3350                              <1> 	; INPUTS ->
  3351                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3352                              <1> 	;    u.fp - list of entries in the fsp table
  3353                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3354                              <1> 	; OUTPUTS ->
  3355                              <1> 	;    r1 - contains the same file descriptor
  3356                              <1> 	;    r2 - contains i-number
  3357                              <1> 	;
  3358                              <1> 	; ((AX = R1))
  3359                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3360                              <1> 	;
  3361                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3362                              <1> 	;              if i-number of the file is 0. (error)  	
  3363                              <1> 
  3364                              <1> 	;movzx	edx, ax ; **
  3365                              <1> 	; 03/02/2022
  3366                              <1> 	;movzx	edx, al
  3367 00004092 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3368 00004094 50                  <1> 	push	eax ; ***
  3369                              <1> 	;push	ax ; ***
  3370                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3371                              <1> 			     ; / the index to u.fp list)
  3372 00004095 E839000000          <1> 	call	getf
  3373                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3374                              <1> 			    ; / cdev has device =, u.fofp 
  3375                              <1> 			    ; / points to 3rd word of fsp entry
  3376 0000409A 6683F801            <1> 	cmp	ax, 1 ; r1
  3377                              <1> 		; tst r1 / is i-number 0?
  3378 0000409E 7231                <1> 	jb	short fclose_2
  3379                              <1> 		; beq 1f / yes, i-node not active so return
  3380                              <1> 		; tst (r0)+ / no, jump over error return
  3381 000040A0 89D3                <1> 	mov	ebx, edx ; **
  3382                              <1> 	; 03/02/2022
  3383 000040A2 89C2                <1> 	mov	edx, eax ; *
  3384                              <1> 	;mov 	dx, ax ; *
  3385                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3386                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3387                              <1> 			    ; / which is index to u.fp ; **
  3388 000040A4 C683[16660000]00    <1> 	mov	byte [ebx+u.fp], 0
  3389                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3390 000040AB 8B1D[20660000]      <1> 	mov	ebx, [u.fofp]
  3391                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3392                              <1> fclose_0:
  3393 000040B1 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3394                              <1> 		; decb 2(r1) / decrement the number of processes 
  3395                              <1> 			   ; / that have opened the file
  3396 000040B4 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3397                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3398                              <1> 	;
  3399                              <1> 	; 03/02/2022
  3400 000040B6 52                  <1> 	push	edx ; *
  3401                              <1> 	;push	dx ; *
  3402                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3403                              <1> 	;xor	ax, ax ; 0
  3404                              <1> 	; 03/02/2022
  3405 000040B7 31C0                <1> 	xor	eax, eax
  3406 000040B9 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3407                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3408 000040BD 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3409                              <1> 		; tstb	3(r1) / has this file been deleted
  3410 000040C0 20C0                <1> 	and	al, al
  3411 000040C2 7407                <1> 	jz	short fclose_1
  3412                              <1> 		; beq 2f / no, branch
  3413                              <1> 	; 03/02/2022
  3414 000040C4 89D0                <1> 	mov	eax, edx
  3415                              <1> 	;mov	ax, dx ; *
  3416                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3417                              <1> 	; AX = inode number
  3418 000040C6 E8A7040000          <1> 	call	anyi
  3419                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3420                              <1> 			    ; / check if file appears in fsp again
  3421                              <1> fclose_1: ; 2:
  3422                              <1> 	; 03/02/2022
  3423 000040CB 58                  <1> 	pop	eax ; * 
  3424                              <1> 	;pop	ax ; *
  3425                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3426 000040CC E8E5110000          <1> 	call	iclose ; close if it is special file 
  3427                              <1> 		; jsr r0,iclose / check to see if its a special file
  3428                              <1> fclose_2: ; 1:
  3429                              <1> 	; 03/02/2022
  3430 000040D1 58                  <1> 	pop	eax ; ***
  3431                              <1> 	;pop	ax ; ***
  3432                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3433 000040D2 C3                  <1> 	retn
  3434                              <1> 		; rts r0
  3435                              <1> 
  3436                              <1> getf:	; / get the device number and the i-number of an open file
  3437                              <1> 	; 03/02/2022
  3438                              <1> 	; 13/05/2015
  3439                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3440                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3441                              <1> 	;
  3442 000040D3 89C3                <1> 	mov	ebx, eax
  3443                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3444                              <1> 	; 03/02/2022
  3445 000040D5 29C0                <1> 	sub	eax, eax
  3446                              <1> 	;
  3447 000040D7 83FB0A              <1> 	cmp	ebx, 10
  3448                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3449 000040DA 732B                <1>         jnb	short getf2 ; 13/05/2015
  3450                              <1> 	;jnb	error
  3451                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3452                              <1> 			    ; / index in fsp table
  3453                              <1> 	; 03/02/2022
  3454 000040DC 8A83[16660000]      <1> 	mov	al, [ebx+u.fp]
  3455                              <1> 	;mov	bl, [ebx+u.fp]
  3456                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3457                              <1> 		                  ; / in fsp table
  3458                              <1> 	; 03/02/2022
  3459 000040E2 08C0                <1> 	or	al, al
  3460 000040E4 7421                <1> 	jz	short getf2
  3461                              <1> 	;or	bl, bl
  3462                              <1> 	;jnz	short getf3
  3463                              <1> 	;;jz	short getf4
  3464                              <1> 		; beq 1f / if its zero return
  3465                              <1> ;getf2:
  3466                              <1> ;	; 'File not open !' error (ax=0)
  3467                              <1> ;	sub	eax, eax
  3468                              <1> ;	retn
  3469                              <1> 
  3470                              <1> getf3:	
  3471                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3472                              <1> 	;
  3473                              <1> 	; 'fsp' table (10 bytes/entry)
  3474                              <1> 	; bit 15				   bit 0
  3475                              <1> 	; ---|-------------------------------------------
  3476                              <1> 	; r/w|		i-number of open file
  3477                              <1> 	; ---|-------------------------------------------
  3478                              <1> 	;		   device number
  3479                              <1> 	; -----------------------------------------------
  3480                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3481                              <1> 	; -----------------------------------------------
  3482                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3483                              <1> 	; ----------------------|------------------------
  3484                              <1> 	;  flag that says file 	| number of processes
  3485                              <1> 	;   has been deleted	| that have file open 
  3486                              <1> 	; ----------------------|------------------------
  3487                              <1> 	;
  3488                              <1> 	;mov	eax, 10
  3489                              <1> 	; 03/02/2022
  3490 000040E6 B30A                <1> 	mov	bl, 10
  3491 000040E8 F6E3                <1> 	mul	bl
  3492 000040EA BB[CE630000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3493 000040EF 01C3                <1> 	add	ebx, eax
  3494                              <1> 		; asl r1
  3495                              <1> 		; asl r1 / multiply by 8 to get index into 
  3496                              <1> 		       ; / fsp table entry
  3497                              <1> 		; asl r1
  3498                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3499                              <1> 			      ; / in the fsp entry
  3500 000040F1 891D[20660000]      <1> 	mov	[u.fofp], ebx
  3501                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3502                              <1> 			      ; / in fsp entry in u.fofp
  3503 000040F7 4B                  <1> 	dec	ebx
  3504 000040F8 4B                  <1> 	dec	ebx
  3505                              <1> 	;mov	al, [ebx]
  3506 000040F9 668B03              <1> 	mov	ax, [ebx]
  3507                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3508 000040FC 66A3[F4650000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3509                              <1> 			     ;;dev number is in 1 byte
  3510                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3511 00004102 4B                  <1> 	dec	ebx
  3512 00004103 4B                  <1> 	dec	ebx
  3513 00004104 668B03              <1> 	mov	ax, [ebx]
  3514                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3515                              <1> getf2:	; 03/02/2022
  3516                              <1> getf4:	; 1:
  3517 00004107 C3                  <1> 	retn
  3518                              <1> 		; rts r0
  3519                              <1> 
  3520                              <1> namei:
  3521                              <1> 	; 15/05/2022
  3522                              <1> 	; 14/05/2022 (mounted directory path, '..' method)
  3523                              <1> 	; 03/02/2022
  3524                              <1> 	; 18/10/2015 (nbase, ncount)
  3525                              <1> 	; 12/10/2015
  3526                              <1> 	; 21/08/2015
  3527                              <1> 	; 18/07/2015
  3528                              <1> 	; 02/07/2015
  3529                              <1> 	; 17/06/2015
  3530                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3531                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3532                              <1> 	;
  3533                              <1> 	; 'namei' takes a file path name and returns i-number of
  3534                              <1> 	; the file in the current directory or the root directory
  3535                              <1> 	; (if the first character of the pathname is '/').	
  3536                              <1> 	;
  3537                              <1> 	; INPUTS ->
  3538                              <1> 	;    u.namep - points to a file path name
  3539                              <1> 	;    u.cdir - i-number of users directory
  3540                              <1> 	;    u.cdev - device number on which user directory resides	
  3541                              <1> 	; OUTPUTS ->
  3542                              <1> 	;    r1 - i-number of file
  3543                              <1> 	;    cdev
  3544                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3545                              <1> 	;               occurs in the search for file path name.
  3546                              <1> 	;	        If no match u.dirb points to the end of 
  3547                              <1> 	;               the directory and r1 = i-number of the current
  3548                              <1> 	;	        directory.	
  3549                              <1> 	; ((AX = R1))
  3550                              <1> 	;
  3551                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3552                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3553                              <1> 	;
  3554                              <1> 
  3555 00004108 66A1[14660000]      <1> 	mov	ax, [u.cdir]
  3556                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3557                              <1> 			      ; / in r1
  3558 0000410E 668B15[54660000]    <1> 	mov	dx, [u.cdrv]
  3559 00004115 668915[F4650000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3560                              <1> 				    ; device/drive number is in 1 byte, 
  3561                              <1> 				    ; not in 1 word!
  3562                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3563                              <1> 				; / into cdev
  3564                              <1> 	; 12/10/2015
  3565                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3566                              <1>       	 ; convert virtual (pathname) addr to physical address
  3567 0000411C E869010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3568                              <1> 		; esi = physical address of [u.namep]
  3569                              <1> 		; ecx = byte count in the page
  3570 00004121 803E2F              <1> 	cmp	byte [esi], '/'
  3571                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3572 00004124 751D                <1> 	jne	short namei_1
  3573                              <1> 		; bne 1f
  3574 00004126 FF05[28660000]      <1> 	inc	dword [u.namep]
  3575                              <1> 		; inc u.namep / go to next char
  3576                              <1> 	; 03/02/2022
  3577 0000412C 49                  <1> 	dec	ecx
  3578                              <1> 	;dec	cx ; remain byte count in the page
  3579 0000412D 7506                <1> 	jnz	short namei_0
  3580                              <1> 	; 12/10/2015
  3581 0000412F E856010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3582                              <1> 		; esi = physical address (page start + offset)
  3583                              <1> 		; ecx = byte count in the page
  3584 00004134 4E                  <1> 	dec	esi
  3585                              <1> namei_0:
  3586 00004135 46                  <1> 	inc 	esi  ; go to next char
  3587 00004136 66A1[FE650000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3588                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3589 0000413C C605[F4650000]00    <1> 	mov	byte [cdev], 0
  3590                              <1> 		; clr cdev / clear device number
  3591                              <1> namei_1: ; 1:
  3592 00004143 F606FF              <1> 	test	byte [esi], 0FFh
  3593                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3594 00004146 74BF                <1> 	jz	short getf4
  3595                              <1> 	;jz	nig
  3596                              <1> 		; tstb *u.namep / is the character in file name a nul
  3597                              <1> 		; beq nig / yes, end of file name reached; 
  3598                              <1> 			; / branch to "nig"
  3599                              <1> namei_2: ; 1:
  3600                              <1> 	; 18/10/2015
  3601 00004148 8935[80660000]      <1> 	mov 	[nbase], esi
  3602 0000414E 66890D[84660000]    <1> 	mov 	[ncount], cx
  3603                              <1> 	;
  3604                              <1> 	;mov	dx, 2
  3605 00004155 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3606 00004157 E895080000          <1> 	call	access
  3607                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3608                              <1> 	; 'access' will not return here if user has not "r" permission !
  3609                              <1> 	; 03/02/2022
  3610 0000415C F605[05630000]40    <1> 	test	byte [i.flgs+1], 40h
  3611                              <1> 	;test 	word [i.flgs], 4000h
  3612                              <1> 		; bit $40000,i.flgs / directory i-node?
  3613 00004163 746A                <1>         jz      short namei_err
  3614                              <1> 		; beq error3 / no, got an error
  3615                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3616 00004165 31C0                <1> 	xor	eax, eax
  3617 00004167 A3[2C660000]        <1> 	mov	[u.off], eax ; 0
  3618 0000416C 66A1[08630000]      <1> 	mov	ax, [i.size]
  3619 00004172 A3[24660000]        <1> 	mov	[u.dirp], eax
  3620                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3621                              <1> 		; clr u.off / u.off is file offset used by user
  3622 00004177 C705[20660000]-     <1> 	mov	dword [u.fofp], u.off
  3622 0000417D [2C660000]          <1>
  3623                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3624                              <1> 				  ; / the offset portion of fsp entry
  3625                              <1> namei_3: ; 2:
  3626 00004181 C705[30660000]-     <1> 	mov	dword [u.base], u.dirbuf
  3626 00004187 [42660000]          <1>
  3627                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3628                              <1> 				    ; / copied from a directory
  3629 0000418B C705[34660000]0A00- <1> 	mov 	dword [u.count], 10 	
  3629 00004193 0000                <1>
  3630                              <1>  		; mov $10.,u.count / u.count is byte count 
  3631                              <1> 				 ; / for reads and writes
  3632 00004195 66A1[F0650000]      <1> 	mov 	ax, [ii]
  3633                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3634 0000419B FE05[71660000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3635 000041A1 E84B090000          <1>     	call	readi
  3636                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3637                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3638 000041A6 8B0D[38660000]      <1> 	mov 	ecx, [u.nread]
  3639 000041AC 09C9                <1> 	or 	ecx, ecx
  3640                              <1> 		; tst u.nread
  3641 000041AE 741B                <1> 	jz	short nib
  3642                              <1> 		; ble nib / gives error return
  3643                              <1> 	;
  3644 000041B0 668B1D[42660000]    <1> 	mov 	bx, [u.dirbuf]
  3645 000041B7 6621DB              <1> 	and 	bx, bx       
  3646                              <1> 		; tst u.dirbuf /
  3647 000041BA 7522                <1> 	jnz	short namei_4
  3648                              <1> 		; bne 3f / branch when active directory entry 
  3649                              <1> 		       ; / (i-node word in entry non zero)
  3650 000041BC A1[2C660000]        <1> 	mov	eax, [u.off]
  3651 000041C1 83E80A              <1> 	sub	eax, 10
  3652 000041C4 A3[24660000]        <1> 	mov	[u.dirp], eax
  3653                              <1> 		; mov u.off,u.dirp
  3654                              <1> 		; sub $10.,u.dirp
  3655 000041C9 EBB6                <1> 	jmp	short namei_3
  3656                              <1> 		; br 2b
  3657                              <1> 
  3658                              <1> 	; 18/07/2013
  3659                              <1> nib: 
  3660 000041CB 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3661 000041CD F9                  <1> 	stc
  3662                              <1> nig:
  3663 000041CE C3                  <1> 	retn
  3664                              <1> 
  3665                              <1> namei_err:
  3666                              <1> 	; 16/06/2015
  3667 000041CF C705[5F660000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3667 000041D7 0000                <1>
  3668 000041D9 E929F0FFFF          <1> 	jmp	error
  3669                              <1> 
  3670                              <1> namei_4: ; 3:
  3671                              <1> 	; 18/10/2015
  3672                              <1> 	; 12/10/2015
  3673                              <1> 	; 21/08/2015
  3674                              <1> 	; 18/07/2015
  3675 000041DE 8B2D[28660000]      <1> 	mov	ebp, [u.namep]
  3676                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3677 000041E4 BF[44660000]        <1> 	mov 	edi, u.dirbuf + 2
  3678                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3679                              <1> 	; 18/10/2015
  3680 000041E9 8B35[80660000]      <1> 	mov	esi, [nbase]	
  3681 000041EF 668B0D[84660000]    <1> 	mov	cx, [ncount]
  3682                              <1> 	;
  3683 000041F6 6621C9              <1> 	and	cx, cx
  3684 000041F9 7505                <1> 	jnz	short namei_5	
  3685                              <1> 	;
  3686 000041FB E890000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3687                              <1> 		; esi = physical address (page start + offset)
  3688                              <1> 		; ecx = byte count in the page
  3689                              <1> namei_5: ; 3:
  3690 00004200 45                  <1> 	inc	ebp ; 18/07/2015
  3691 00004201 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3692                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3693 00004202 08C0                <1> 	or 	al, al
  3694 00004204 741C                <1> 	jz 	short namei_7
  3695                              <1> 		; beq 3f / if char is nul, then the last char in string
  3696                              <1> 			; / has been moved
  3697 00004206 3C2F                <1> 	cmp	al, '/'
  3698                              <1> 		; cmp r4,$'/ / is char a </>
  3699 00004208 7418                <1> 	je 	short namei_7
  3700                              <1> 		; beq 3f
  3701                              <1> 	; 03/02/2022
  3702 0000420A 49                  <1> 	dec	ecx	
  3703                              <1> 	; 12/10/2015
  3704                              <1> 	;dec	cx ; remain byte count in the page
  3705 0000420B 7505                <1> 	jnz	short namei_6
  3706 0000420D E87E000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3707                              <1> 		; esi = physical address (page start + offset)
  3708                              <1> 		; ecx = byte count in the page
  3709                              <1> namei_6:
  3710 00004212 81FF[4C660000]      <1>         cmp     edi, u.dirbuf + 10
  3711                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3712                              <1> 				     ; / all 8 bytes of file name
  3713 00004218 74E6                <1> 	je	short namei_5
  3714                              <1> 		; beq 3b
  3715 0000421A AE                  <1> 	scasb	
  3716                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3717                              <1> 			      ; / char read from directory
  3718 0000421B 74E3                <1> 	je 	short namei_5
  3719                              <1> 		; beq 3b / branch if chars match
  3720                              <1> namei_9:
  3721 0000421D E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3722                              <1> 		; br 2b / file names do not match go to next directory entry
  3723                              <1> namei_7: ; 3:
  3724 00004222 81FF[4C660000]      <1> 	cmp	edi, u.dirbuf + 10
  3725                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3726 00004228 7406                <1> 	je	short namei_8
  3727                              <1> 		; beq 3f
  3728 0000422A 8A27                <1> 	mov 	ah, [edi]
  3729                              <1> 	;inc 	edi 
  3730 0000422C 20E4                <1> 	and 	ah, ah
  3731                              <1> 		; tstb (r3)+ /
  3732                              <1>         ;jnz	namei_3
  3733                              <1> 		; bne 2b
  3734                              <1> 	; 03/02/2020
  3735 0000422E 75ED                <1> 	jnz	short namei_9
  3736                              <1> namei_8: ; 3
  3737 00004230 892D[28660000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3738                              <1> 		; mov r2,u.namep / u.namep points to char 
  3739                              <1> 			       ; / following a / or nul
  3740                              <1> 	;mov	bx, [u.dirbuf]
  3741                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3742                              <1> 				; / entry to r1
  3743                              <1> 	;;;;
  3744                              <1> 	; 14/05/2022 - Retro UNIX (8086/386) feature only !
  3745                              <1> 	; ! 'pwd' utility modification !
  3746                              <1> 	; ((if directory entry name is a dotdot)))
  3747                              <1> 	;; check if it is mounted device's root directory inode
  3748                              <1> 	; and if so, replace it with parent dir inode number
  3749                              <1> 	;  of mounting directory in [mntp].
  3750                              <1> 
  3751 00004236 668B1D[42660000]    <1> 	mov	bx, [u.dirbuf]
  3752                              <1> 
  3753 0000423D 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3754 00004241 753C                <1> 	jne	short namei_11
  3755                              <1> 
  3756 00004243 663B1D[F0650000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3757 0000424A 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3758                              <1> 
  3759                              <1> 	;cmp	[idev], bh ; 0
  3760 0000424C 383D[F4650000]      <1> 	cmp	[cdev], bh ; 0
  3761                              <1> 			; 0 = root fs, dev num in [rdev]
  3762                              <1> 			; 1 = mounted, dev num in [mdev]
  3763 00004252 762B                <1> 	jna	short namei_11
  3764                              <1> 
  3765                              <1> 	; dotdot (parent directory link) check
  3766 00004254 66813D[44660000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3766 0000425C 2E                  <1>
  3767 0000425D 7520                <1> 	jne	short namei_11
  3768 0000425F 803D[46660000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3769 00004266 7517                <1> 	jne	short namei_11
  3770                              <1> 	
  3771                              <1> 	; (This may not be necessary because [idev] = 1
  3772                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3773 00004268 66391D[F8650000]    <1> 	cmp	[mnti], bx ; 41
  3774 0000426F 760E                <1> 	jna	short namei_11
  3775                              <1> 	
  3776                              <1> 	; change inumber to parent dir inum of mount directory
  3777 00004271 668B1D[FA650000]    <1> 	mov	bx, [mntp]
  3778 00004278 C605[F4650000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3779                              <1> namei_11:
  3780                              <1> 	;;;;
  3781                              <1> 
  3782 0000427F 20C0                <1> 	and 	al, al
  3783                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3784                              <1> 		      ;  / if r4 = </> then go to next directory
  3785                              <1> 	; 15/05/2022
  3786 00004281 6689D8              <1> 	mov	ax, bx
  3787                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3788                              <1>   	; 03/02/2022
  3789 00004284 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3790                              <1> 	;jnz	namei_2 
  3791                              <1> 		; bne 1b
  3792                              <1> 	; AX = i-number of the file
  3793                              <1> ;;nig:
  3794 00004289 C3                  <1> 	retn
  3795                              <1> 		; tst (r0)+ / gives non-error return
  3796                              <1> ;;nib:
  3797                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3798                              <1> 		       ; ax = 0 -> file not found 
  3799                              <1> ;;	stc	; 27/05/2013
  3800                              <1> ;;	retn
  3801                              <1> 		; rts r0
  3802                              <1> 
  3803                              <1> trans_addr_nmbp:
  3804                              <1> 	; 03/02/2022
  3805                              <1> 	; 18/10/2015
  3806                              <1> 	; 12/10/2015
  3807 0000428A 8B2D[28660000]      <1> 	mov 	ebp, [u.namep]
  3808                              <1> trans_addr_nm:
  3809                              <1> 	; 03/02/2022
  3810                              <1> 	; Convert virtual (pathname) address to physical address
  3811                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3812                              <1> 	; 18/10/2015
  3813                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3814                              <1> 	; 02/07/2015
  3815                              <1> 	; 17/06/2015
  3816                              <1> 	; 16/06/2015
  3817                              <1> 	;
  3818                              <1> 	; INPUTS: 
  3819                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3820                              <1> 	;	[u.pgdir] = user's page directory
  3821                              <1> 	; OUTPUT:
  3822                              <1> 	;       esi = physical address of the pathname
  3823                              <1> 	;	ecx = remain byte count in the page
  3824                              <1> 	;
  3825                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3826                              <1> 	;
  3827                              <1> 
  3828                              <1> 	; 03/02/2022
  3829 00004290 29C9                <1> 	sub	ecx, ecx
  3830                              <1> 
  3831 00004292 833D[67660000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3832 00004299 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3833                              <1> 				     ; it is already physical address
  3834 0000429B 50                  <1>    	push	eax	
  3835 0000429C 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3836 0000429E E849E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3837 000042A3 7204                <1> 	jc	short tr_addr_nm_err
  3838                              <1> 	; 18/10/2015
  3839                              <1> 	; eax = physical address 
  3840                              <1> 	; cx = remain byte count in page (1-4096) 
  3841                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3842 000042A5 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3843 000042A7 58                  <1> 	pop	eax 
  3844 000042A8 C3                  <1> 	retn
  3845                              <1> 
  3846                              <1> tr_addr_nm_err:
  3847 000042A9 A3[5F660000]        <1> 	mov	[u.error], eax
  3848                              <1> 	;pop 	eax
  3849 000042AE E954EFFFFF          <1> 	jmp	error
  3850                              <1> 
  3851                              <1> trans_addr_nmk:
  3852                              <1> 	; 12/10/2015
  3853                              <1> 	; 02/07/2015
  3854 000042B3 8B35[28660000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3855                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3856                              <1> 	; 03/02/2022
  3857 000042B9 B510                <1> 	mov	ch, PAGE_SIZE/256
  3858 000042BB C3                  <1> 	retn
  3859                              <1> 
  3860                              <1> syschdir:
  3861                              <1> 	; 03/02/2022
  3862                              <1> 	; / makes the directory specified in the argument
  3863                              <1> 	; / the current directory
  3864                              <1> 	;
  3865                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3866                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3867                              <1> 	;
  3868                              <1> 	; 'syschdir' makes the directory specified in its argument
  3869                              <1> 	; the current working directory.
  3870                              <1> 	;
  3871                              <1> 	; Calling sequence:
  3872                              <1> 	;	syschdir; name
  3873                              <1> 	; Arguments:
  3874                              <1> 	;	name - address of the path name of a directory
  3875                              <1> 	;	       terminated by nul byte.	
  3876                              <1> 	; Inputs: -
  3877                              <1> 	; Outputs: -
  3878                              <1> 	; ...............................................................
  3879                              <1> 	;				
  3880                              <1> 	; Retro UNIX 8086 v1 modification:
  3881                              <1> 	;	 The user/application program puts address of 
  3882                              <1> 	;	 the path name in BX register as 'syschdir' 
  3883                              <1> 	; 	 system call argument.
  3884                              <1> 
  3885 000042BC 891D[28660000]      <1> 	mov	[u.namep], ebx
  3886                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3887 000042C2 E841FEFFFF          <1> 	call	namei
  3888                              <1> 		; jsr r0,namei / find its i-number
  3889                              <1> 	;jc	error
  3890                              <1> 		; br error3
  3891 000042C7 730F                <1> 	jnc	short syschdir0
  3892                              <1> 	; 'directory not found !' error
  3893 000042C9 C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3893 000042D1 0000                <1>
  3894 000042D3 E92FEFFFFF          <1> 	jmp	error
  3895                              <1> syschdir0:
  3896                              <1> 	; 03/02/2022
  3897 000042D8 B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3898 000042DA E812070000          <1> 	call	access
  3899                              <1> 		; jsr r0,access; 2 / get i-node into core
  3900                              <1> 	; 03/02/2022
  3901 000042DF F605[05630000]40    <1> 	test	byte [i.flgs+1], 40h
  3902                              <1> 	;test	word [i.flgs], 4000h
  3903                              <1> 		; bit $40000,i.flgs / is it a directory?
  3904                              <1> 	;jz	error 
  3905                              <1> 		; beq error3 / no error
  3906 000042E6 750F                <1> 	jnz	short syschdir1
  3907 000042E8 C705[5F660000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3907 000042F0 0000                <1>
  3908 000042F2 E910EFFFFF          <1> 	jmp	error
  3909                              <1> syschdir1:
  3910 000042F7 66A3[14660000]      <1> 	mov	[u.cdir], ax
  3911                              <1> 		; mov r1,u.cdir / move i-number to users 
  3912                              <1> 			      ; / current directory
  3913 000042FD 66A1[F4650000]      <1> 	mov	ax, [cdev]
  3914 00004303 66A3[54660000]      <1> 	mov	[u.cdrv], ax
  3915                              <1> 		; mov cdev,u.cdev / move its device to users 
  3916                              <1> 			        ; / current device
  3917 00004309 E919EFFFFF          <1> 	jmp	sysret
  3918                              <1> 		; br sysret3
  3919                              <1> 	
  3920                              <1> syschmod: ; < change mode of file >
  3921                              <1> 	; 29/04/2022 (bugfix)
  3922                              <1> 	; 03/02/2022
  3923                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3924                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3925                              <1> 	;
  3926                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3927                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3928                              <1> 	; changed to 'mode'.
  3929                              <1> 	;
  3930                              <1> 	; Calling sequence:
  3931                              <1> 	;	syschmod; name; mode
  3932                              <1> 	; Arguments:
  3933                              <1> 	;	name - address of the file name
  3934                              <1> 	;	       terminated by null byte.
  3935                              <1> 	;	mode - (new) mode/flags < attributes >
  3936                              <1> 	;	
  3937                              <1> 	; Inputs: -
  3938                              <1> 	; Outputs: -
  3939                              <1> 	; ...............................................................
  3940                              <1> 	;				
  3941                              <1> 	; Retro UNIX 8086 v1 modification: 
  3942                              <1> 	;       'syschmod' system call has two arguments; so,
  3943                              <1> 	;	* 1st argument, name is pointed to by BX register
  3944                              <1> 	;	* 2nd argument, mode is in CX register
  3945                              <1> 	;
  3946                              <1> 	; Mode bits (Flags):
  3947                              <1> 	;	bit 0 - write permission for non-owner (1)
  3948                              <1> 	;	bit 1 - read permission for non-owner (2)
  3949                              <1> 	;	bit 2 - write permission for owner (4)
  3950                              <1> 	;	bit 3 - read permission for owner (8)
  3951                              <1> 	;	bit 4 - executable flag (16) 	
  3952                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3953                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3954                              <1> 	;	bit 12 - large file flag (4096)
  3955                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3956                              <1> 	;	bit 14 - directory flag (16384)
  3957                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3958                              <1> 
  3959                              <1> 	; / name; mode
  3960 0000430E E815000000          <1> 	call	isown
  3961                              <1> 		;jsr r0,isown / get the i-node and check user status
  3962                              <1> 	; 03/02/2022
  3963 00004313 F605[05630000]40    <1> 	test	byte [i.flgs+1], 40h
  3964                              <1> 	;test	word [i.flgs], 4000h
  3965                              <1> 		; bit $40000,i.flgs / directory?
  3966 0000431A 7402                <1> 	jz	short syschmod1
  3967                              <1> 		; beq 2f / no
  3968                              <1> 	; AL = (new) mode
  3969 0000431C 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3970                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3971                              <1> 			   ; / executable modes
  3972                              <1> syschmod1: ; 2:
  3973 0000431E A2[04630000]        <1> 	mov	[i.flgs], al	
  3974                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3975                              <1> 	;jmp	short isown1
  3976                              <1> 	;	; br 1f ; (jmp sysret4)
  3977                              <1> 	; 29/04/2022
  3978 00004323 E9FFEEFFFF          <1> 	jmp	sysret
  3979                              <1> 
  3980                              <1> isown:
  3981                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3982                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3983                              <1> 	;
  3984                              <1> 	; 'isown' is given a file name (the 1st argument).
  3985                              <1> 	;  It find the i-number of that file via 'namei' 
  3986                              <1> 	;  then gets the i-node into core via 'iget'.
  3987                              <1> 	;  It then tests to see if the user is super user. 
  3988                              <1> 	;  If not, it cheks to see if the user is owner of 
  3989                              <1> 	;  the file. If he is not an error occurs.
  3990                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3991                              <1> 	;  the inode has been modificed and the 2nd argument of
  3992                              <1> 	;  the call is put in r2.
  3993                              <1> 	;
  3994                              <1> 	; INPUTS ->
  3995                              <1> 	;    arguments of syschmod and syschown calls
  3996                              <1> 	; OUTPUTS ->
  3997                              <1> 	;    u.uid - id of user
  3998                              <1> 	;    imod - set to a 1
  3999                              <1> 	;    r2 - contains second argument of the system call				 	
  4000                              <1> 	;
  4001                              <1> 	;   ((AX=R2) output as 2nd argument)
  4002                              <1> 	;
  4003                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4004                              <1> 	;
  4005                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4006                              <1> 	;; ! 2nd argument on top of stack !
  4007                              <1> 	;; 22/06/2015 - 32 bit modifications
  4008                              <1> 	;; 07/07/2013
  4009 00004328 891D[28660000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4010 0000432E 51                  <1> 	push 	ecx ;; 2nd argument
  4011                              <1> 	;;
  4012 0000432F E8D4FDFFFF          <1> 	call	namei
  4013                              <1> 		; jsr r0,namei / get its i-number
  4014                              <1>        ; Retro UNIX 8086 v1 modification !
  4015                              <1>        ; ax = 0 -> file not found 
  4016                              <1> 	;and	ax, ax
  4017                              <1> 	;jz	error
  4018                              <1> 	;jc	error ; 27/05/2013
  4019                              <1> 		; br error3
  4020 00004334 730F                <1> 	jnc	short isown0
  4021                              <1> 	; 'file not found !' error
  4022 00004336 C705[5F660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4022 0000433E 0000                <1>
  4023 00004340 E9C2EEFFFF          <1> 	jmp	error
  4024                              <1> isown0:
  4025 00004345 E8D3050000          <1> 	call	iget
  4026                              <1> 		; jsr r0,iget / get i-node into core
  4027 0000434A A0[56660000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4028 0000434F 08C0                <1> 	or	al, al
  4029                              <1> 		; tstb u.uid / super user?
  4030 00004351 7417                <1> 	jz	short isown1
  4031                              <1> 		; beq 1f / yes, branch
  4032 00004353 3A05[07630000]      <1> 	cmp	al, [i.uid]
  4033                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4034                              <1> 				 ; / the file
  4035                              <1> 	;jne	error
  4036                              <1> 		; beq 1f / yes
  4037                              <1> 		; jmp error3 / no, error
  4038 00004359 740F                <1> 	je	short isown1
  4039                              <1> 
  4040 0000435B C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4040 00004363 0000                <1>
  4041                              <1> 			;  'permission denied !' error
  4042 00004365 E99DEEFFFF          <1> 	jmp	error
  4043                              <1> isown1: ; 1:
  4044 0000436A E8B8060000          <1> 	call	setimod
  4045                              <1> 		; jsr r0,setimod / indicates 
  4046                              <1> 		;	       ; / i-node has been modified
  4047 0000436F 58                  <1> 	pop	eax ; 2nd argument
  4048                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4049                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4050 00004370 C3                  <1> 	retn
  4051                              <1> 		; rts r0
  4052                              <1> 
  4053                              <1> ;;arg:  ; < get system call arguments >
  4054                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4055                              <1> 	; of form:
  4056                              <1> 	;	sys 'routine' ; arg1
  4057                              <1> 	;		or
  4058                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4059                              <1> 	;		or
  4060                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4061                              <1> 	;	
  4062                              <1> 	; INPUTS ->
  4063                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4064                              <1> 	;	This pointers's value is actually the value of
  4065                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4066                              <1> 	;	made to process the sys instruction
  4067                              <1> 	;    r0 - contains the return address for the routine
  4068                              <1> 	;	that called arg. The data in the word pointer 
  4069                              <1> 	;	to by the return address is used as address
  4070                              <1> 	;	in which the extracted argument is stored   		
  4071                              <1> 	;    	
  4072                              <1> 	; OUTPUTS ->
  4073                              <1> 	;    'address' - contains the extracted argument 
  4074                              <1> 	;    u.sp+18 - is incremented by 2 
  4075                              <1> 	;    r1 - contains the extracted argument
  4076                              <1> 	;    r0 - points to the next instruction to be
  4077                              <1> 	;	 executed in the calling routine.
  4078                              <1> 	;
  4079                              <1>   
  4080                              <1> 	; mov u.sp,r1
  4081                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4082                              <1> 			; / into argument of arg2
  4083                              <1> 	; add $2,18.(r1) / point pc on stack 
  4084                              <1> 			      ; / to next system argument
  4085                              <1> 	; rts r0
  4086                              <1> 
  4087                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4088                              <1> 	; 'arg2' takes first argument in system call
  4089                              <1> 	;  (pointer to name of the file) and puts it in location
  4090                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4091                              <1> 	;  and on top of the stack
  4092                              <1> 	;	
  4093                              <1> 	; INPUTS ->
  4094                              <1> 	;    u.sp, r0
  4095                              <1> 	;    	
  4096                              <1> 	; OUTPUTS ->
  4097                              <1> 	;    u.namep
  4098                              <1> 	;    u.off 
  4099                              <1> 	;    u.off pushed on stack
  4100                              <1> 	;    r1
  4101                              <1> 	;
  4102                              <1> 
  4103                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4104                              <1> 				; / first arg in sys call
  4105                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4106                              <1> 				; / second arg in sys call
  4107                              <1> 	; mov r0,r1 / r0 points to calling routine
  4108                              <1> 	; mov (sp),r0 / put operation code back in r0
  4109                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4110                              <1> 			; / on stack
  4111                              <1> 	; jmp (r1) / return to calling routine
  4112                              <1> 
  4113                              <1> syschown: ; < change owner of file >
  4114                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4115                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4116                              <1> 	;
  4117                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4118                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4119                              <1> 	; changed to 'owner'
  4120                              <1> 	;
  4121                              <1> 	; Calling sequence:
  4122                              <1> 	;	syschown; name; owner
  4123                              <1> 	; Arguments:
  4124                              <1> 	;	name - address of the file name
  4125                              <1> 	;	       terminated by null byte.
  4126                              <1> 	;	owner - (new) owner (number/ID)
  4127                              <1> 	;	
  4128                              <1> 	; Inputs: -
  4129                              <1> 	; Outputs: -
  4130                              <1> 	; ...............................................................
  4131                              <1> 	;				
  4132                              <1> 	; Retro UNIX 8086 v1 modification: 
  4133                              <1> 	;       'syschown' system call has two arguments; so,
  4134                              <1> 	;	* 1st argument, name is pointed to by BX register
  4135                              <1> 	;	* 2nd argument, owner number is in CX register
  4136                              <1> 	;
  4137                              <1> 	; / name; owner
  4138 00004371 E8B2FFFFFF          <1> 	call	isown
  4139                              <1> 		; jsr r0,isown / get the i-node and check user status
  4140 00004376 803D[56660000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4141                              <1> 		; tstb u.uid / super user
  4142 0000437D 7418                <1> 	jz	short syschown1
  4143                              <1> 		; beq 2f / yes, 2f
  4144 0000437F F605[04630000]20    <1>         test    byte [i.flgs], 20h ; 32
  4145                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4146                              <1> 	;jnz	error
  4147                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4148 00004386 740F                <1> 	jz	short syschown1
  4149                              <1> 	; 'permission denied !'
  4150 00004388 C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4150 00004390 0000                <1>
  4151 00004392 E970EEFFFF          <1> 	jmp	error
  4152                              <1> syschown1: ; 2:
  4153                              <1> 	; AL = owner (number/ID)
  4154 00004397 A2[07630000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4155                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4156                              <1> 			       ; / in the i-node
  4157 0000439C E986EEFFFF          <1> 	jmp	sysret
  4158                              <1> 	; 1: 
  4159                              <1> 		; jmp sysret4
  4160                              <1> 	; 3:
  4161                              <1> 		; jmp	error
  4162                              <1> 
  4163                              <1> systime: ; / get time of year
  4164                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4165                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4166                              <1> 	;
  4167                              <1> 	; 20/06/2013
  4168                              <1> 	; 'systime' gets the time of the year.
  4169                              <1> 	; The present time is put on the stack.
  4170                              <1> 	;
  4171                              <1> 	; Calling sequence:
  4172                              <1> 	;	systime
  4173                              <1> 	; Arguments: -
  4174                              <1> 	;	
  4175                              <1> 	; Inputs: -
  4176                              <1> 	; Outputs: sp+2, sp+4 - present time
  4177                              <1> 	; ...............................................................
  4178                              <1> 	;	
  4179                              <1> 	; Retro UNIX 8086 v1 modification: 
  4180                              <1> 	;       'systime' system call will return to the user
  4181                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4182                              <1> 	;
  4183                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4184                              <1> 	;	system call for PC compatibility !!		 	
  4185                              <1> 
  4186 000043A1 E8AFE9FFFF          <1> 	call 	epoch
  4187 000043A6 A3[10660000]        <1> 	mov 	[u.r0], eax
  4188                              <1> 		; mov s.time,4(sp)
  4189                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4190                              <1> 				   ; / on the stack
  4191                              <1> 		; br sysret4
  4192 000043AB E977EEFFFF          <1> 	jmp	sysret 
  4193                              <1> 
  4194                              <1> sysstime: ; / set time
  4195                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4196                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4197                              <1> 	;
  4198                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4199                              <1> 	;
  4200                              <1> 	; Calling sequence:
  4201                              <1> 	;	sysstime
  4202                              <1> 	; Arguments: -
  4203                              <1> 	;	
  4204                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4205                              <1> 	; Outputs: -
  4206                              <1> 	; ...............................................................
  4207                              <1> 	;	
  4208                              <1> 	; Retro UNIX 8086 v1 modification: 
  4209                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4210                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4211                              <1> 	; 
  4212                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4213                              <1> 	;	to get sysstime system call arguments from the user;
  4214                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4215                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4216                              <1> 	;
  4217                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4218                              <1> 	;	system call for PC compatibility !!	
  4219                              <1> 
  4220 000043B0 803D[56660000]00    <1> 	cmp	byte [u.uid], 0
  4221                              <1> 		; tstb u.uid / is user the super user
  4222                              <1> 	;ja	error
  4223                              <1> 		; bne error4 / no, error
  4224 000043B7 760F                <1> 	jna	short systime1
  4225                              <1> 	; 'permission denied !'
  4226 000043B9 C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4226 000043C1 0000                <1>
  4227 000043C3 E93FEEFFFF          <1> 	jmp	error
  4228                              <1> systime1:
  4229                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4230                              <1> 	; EBX = unix (epoch) time (from user)
  4231 000043C8 89D8                <1> 	mov	eax, ebx
  4232 000043CA E806EBFFFF          <1> 	call 	set_date_time
  4233                              <1> 		; mov 4(sp),s.time
  4234                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4235 000043CF E953EEFFFF          <1> 	jmp	sysret
  4236                              <1> 		; br sysret4
  4237                              <1> 
  4238                              <1> sysbreak:
  4239                              <1> 	; 18/10/2015
  4240                              <1> 	; 07/10/2015
  4241                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4242                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4243                              <1> 	;
  4244                              <1> 	; 'sysbreak' sets the programs break points. 
  4245                              <1> 	; It checks the current break point (u.break) to see if it is
  4246                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4247                              <1> 	; even address (if it was odd) and the area between u.break
  4248                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4249                              <1> 	; in u.break and control is passed to 'sysret'.
  4250                              <1> 	;
  4251                              <1> 	; Calling sequence:
  4252                              <1> 	;	sysbreak; addr
  4253                              <1> 	; Arguments: -
  4254                              <1> 	;	
  4255                              <1> 	; Inputs: u.break - current breakpoint
  4256                              <1> 	; Outputs: u.break - new breakpoint 
  4257                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4258                              <1> 	; ...............................................................
  4259                              <1> 	;	
  4260                              <1> 	; Retro UNIX 8086 v1 modification:
  4261                              <1> 	;	The user/application program puts breakpoint address
  4262                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4263                              <1> 	; 	(argument transfer method 1)
  4264                              <1> 	;
  4265                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4266                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4267                              <1> 	;  NOTE:
  4268                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4269                              <1> 	;	'u.break' address) of user's memory for original unix's
  4270                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4271                              <1> 
  4272                              <1> 		; mov u.break,r1 / move users break point to r1
  4273                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4274                              <1> 		; blos 1f / yes, 1f
  4275                              <1> 	; 23/06/2015
  4276 000043D4 8B2D[3C660000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4277                              <1> 	;and	ebp, ebp
  4278                              <1> 	;jz	short sysbreak_3 
  4279                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4280                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4281 000043DA 8B15[08660000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4282 000043E0 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4283                              <1> 	; 07/10/2015
  4284 000043E3 891D[3C660000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4285                              <1> 	;
  4286 000043E9 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4287                              <1> 			   ; with top of user's stack (virtual!)
  4288 000043EB 7327                <1> 	jnb	short sysbreak_3
  4289                              <1> 		; cmp r1,sp / is it the same or higher 
  4290                              <1> 			  ; / than the stack?
  4291                              <1> 		; bhis 1f / yes, 1f
  4292 000043ED 89DE                <1> 	mov	esi, ebx
  4293 000043EF 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4294 000043F1 7621                <1> 	jna	short sysbreak_3 
  4295                              <1> 	;push	ebx
  4296                              <1> sysbreak_1:
  4297 000043F3 89EB                <1> 	mov	ebx, ebp  
  4298 000043F5 E8F2E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4299 000043FA 0F82A9FEFFFF        <1> 	jc	tr_addr_nm_err
  4300                              <1> 	; 18/10/2015
  4301 00004400 89C7                <1> 	mov	edi, eax 
  4302 00004402 29C0                <1> 	sub	eax, eax ; 0
  4303                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4304 00004404 39CE                <1> 	cmp	esi, ecx
  4305 00004406 7302                <1> 	jnb	short sysbreak_2
  4306 00004408 89F1                <1> 	mov	ecx, esi
  4307                              <1> sysbreak_2:
  4308 0000440A 29CE                <1> 	sub	esi, ecx
  4309 0000440C 01CD                <1> 	add	ebp, ecx
  4310 0000440E F3AA                <1> 	rep 	stosb
  4311 00004410 09F6                <1> 	or	esi, esi
  4312 00004412 75DF                <1> 	jnz	short sysbreak_1
  4313                              <1> 	;
  4314                              <1> 		; bit $1,r1 / is it an odd address
  4315                              <1> 		; beq 2f / no, its even
  4316                              <1> 		; clrb (r1)+ / yes, make it even
  4317                              <1> 	; 2: / clear area between the break point and the stack
  4318                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4319                              <1> 		; bhis 1f / yes, quit
  4320                              <1> 		; clr (r1)+ / clear word
  4321                              <1> 		; br 2b / go back
  4322                              <1> 	;pop	ebx
  4323                              <1> sysbreak_3: ; 1:
  4324                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4325                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4326                              <1> 			; / in u.break (set new break point)
  4327                              <1> 		; br sysret4 / br sysret
  4328 00004414 E90EEEFFFF          <1> 	jmp	sysret
  4329                              <1> 
  4330                              <1> maknod: 
  4331                              <1> 	; 12/02/2022
  4332                              <1> 	; 03/02/2022
  4333                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4334                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4335                              <1> 	;
  4336                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4337                              <1> 	; for this i-node in the current directory.
  4338                              <1> 	;
  4339                              <1> 	; INPUTS ->
  4340                              <1> 	;    r1 - contains mode
  4341                              <1> 	;    ii - current directory's i-number	
  4342                              <1> 	;    	
  4343                              <1> 	; OUTPUTS ->
  4344                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4345                              <1> 	;    i.flgs - flags in new i-node 
  4346                              <1> 	;    i.uid - filled with u.uid
  4347                              <1> 	;    i.nlks - 1 is put in the number of links
  4348                              <1> 	;    i.ctim - creation time				
  4349                              <1> 	;    i.ctim+2 - modification time
  4350                              <1> 	;    imod - set via call to setimod
  4351                              <1> 	;	
  4352                              <1> 	; ((AX = R1)) input
  4353                              <1> 	;
  4354                              <1> 	; (Retro UNIX Prototype : 
  4355                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4356                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4357                              <1> 
  4358                              <1> 	; / r1 contains the mode
  4359 00004419 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4360                              <1> 		; bis $100000,r1 / allocate flag set
  4361 0000441C 6650                <1> 	push	ax ; *
  4362                              <1> 		; mov r1,-(sp) / put mode on stack
  4363                              <1> 	; 31/07/2013
  4364 0000441E 66A1[F0650000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4365                              <1> 		; mov ii,r1 / move current i-number to r1
  4366 00004424 B201                <1> 	mov	dl, 1 ; owner flag mask
  4367 00004426 E8C6050000          <1> 	call	access	
  4368                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4369                              <1> 	; 03/02/2022
  4370 0000442B 50                  <1> 	push	eax ; **
  4371                              <1> 	;push	ax
  4372                              <1> 		; mov r1,-(sp) / put i-number on stack
  4373 0000442C 66B82800            <1> 	mov	ax, 40
  4374                              <1> 		; mov $40.,r1 / r1 = 40
  4375                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4376 00004430 6640                <1> 	inc	ax
  4377                              <1> 		; inc r1 / r1 = r1 + 1
  4378 00004432 E87F060000          <1> 	call	imap
  4379                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4380                              <1> 			    ; /	inode map in r2 & m
  4381                              <1>   
  4382                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4383                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4384                              <1> 
  4385                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4386                              <1> 	;	       Inode count must be checked here
  4387                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4388                              <1> 
  4389                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4390                              <1> 	; (inode count check)
  4391                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4392                              <1> 
  4393 00004437 730F                <1> 	jnc	short maknod2
  4394                              <1> 
  4395                              <1> 	; no free inode in inode table !
  4396 00004439 C705[5F660000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4396 00004441 0000                <1>
  4397                              <1> 			; miscellaneous/other errors
  4398 00004443 E9BFEDFFFF          <1> 	jmp	error	
  4399                              <1> maknod2: 	
  4400 00004448 8413                <1> 	test	[ebx], dl
  4401                              <1> 		; bitb mq,(r2) / is the i-node active
  4402 0000444A 75E4                <1> 	jnz	short maknod1
  4403                              <1> 		; bne 1b / yes, try the next one
  4404 0000444C 0813                <1> 	or	[ebx], dl
  4405                              <1> 		; bisb mq,(r2) / no, make it active 
  4406                              <1> 			     ; / (put a 1 in the bit map)
  4407 0000444E E8CA040000          <1> 	call	iget
  4408                              <1> 		; jsr r0,iget / get i-node into core
  4409                              <1> 	; 03/02/2022
  4410 00004453 F605[05630000]80    <1> 	test	byte [i.flgs+1], 80h
  4411                              <1> 	;test	word [i.flgs], 8000h 
  4412                              <1> 		; tst i.flgs / is i-node already allocated
  4413 0000445A 75D4                <1> 	jnz	short maknod1	
  4414                              <1> 		; blt 1b / yes, look for another one
  4415 0000445C 66A3[42660000]      <1> 	mov	[u.dirbuf], ax
  4416                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4417                              <1> 	; 03/02/2022
  4418 00004462 58                  <1> 	pop	eax ; **
  4419                              <1> 	;pop	ax
  4420                              <1> 		; mov (sp)+,r1 / get current i-number back
  4421 00004463 E8B5040000          <1> 	call	iget
  4422                              <1> 		; jsr r0,iget / get i-node in core
  4423 00004468 E852F7FFFF          <1> 	call	mkdir
  4424                              <1> 		; jsr r0,mkdir / make a directory entry 
  4425                              <1> 			     ; / in current directory
  4426 0000446D 66A1[42660000]      <1> 	mov	ax, [u.dirbuf]
  4427                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4428 00004473 E8A5040000          <1> 	call	iget
  4429                              <1> 		; jsr r0,iget / get it into core
  4430                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4431                              <1> 	;mov	ecx, 8
  4432                              <1> 	; 03/02/2022 
  4433 00004478 29C9                <1> 	sub	ecx, ecx
  4434 0000447A B108                <1> 	mov	cl, 8
  4435 0000447C 31C0                <1> 	xor	eax, eax ; 0
  4436 0000447E BF[04630000]        <1> 	mov	edi, inode 
  4437 00004483 F3AB                <1> 	rep	stosd
  4438                              <1> 	;
  4439 00004485 668F05[04630000]    <1> 	pop	word [i.flgs] ; *
  4440                              <1> 		; mov (sp)+,i.flgs / fill flags
  4441 0000448C 8A0D[56660000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4442 00004492 880D[07630000]      <1> 	mov 	[i.uid], cl
  4443                              <1> 		; movb u.uid,i.uid / user id	
  4444 00004498 C605[06630000]01    <1> 	mov     byte [i.nlks], 1
  4445                              <1> 		; movb $1,i.nlks / 1 link
  4446                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4447                              <1> 	;mov	eax, [s.time]
  4448                              <1> 	;mov 	[i.ctim], eax
  4449                              <1> 	 	; mov s.time,i.ctim / time created
  4450                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4451                              <1> 	; Retro UNIX 8086 v1 modification !
  4452                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4453                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4454                              <1> 	;call setimod
  4455                              <1> 		; jsr r0,setimod / set modified flag
  4456                              <1> 	;retn
  4457                              <1> 		; rts r0 / return
  4458                              <1> 	; 03/02/2022
  4459 0000449F E983050000          <1> 	jmp	setimod
  4460                              <1> 
  4461                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4462                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4463                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4464                              <1> 	;
  4465                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4466                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4467                              <1> 	; The file descriptor refers to a file open for reading or
  4468                              <1> 	; writing. The read (or write) pointer is set as follows:
  4469                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4470                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4471                              <1> 	;	  current location plus offset.
  4472                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4473                              <1> 	;	  size of file plus offset.
  4474                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4475                              <1> 	;
  4476                              <1> 	; Calling sequence:
  4477                              <1> 	;	sysseek; offset; ptrname
  4478                              <1> 	; Arguments:
  4479                              <1> 	;	offset - number of bytes desired to move 
  4480                              <1> 	;		 the r/w pointer
  4481                              <1> 	;	ptrname - a switch indicated above
  4482                              <1> 	;
  4483                              <1> 	; Inputs: r0 - file descriptor 
  4484                              <1> 	; Outputs: -
  4485                              <1> 	; ...............................................................
  4486                              <1> 	;	
  4487                              <1> 	; Retro UNIX 8086 v1 modification: 
  4488                              <1> 	;       'sysseek' system call has three arguments; so,
  4489                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4490                              <1> 	;	* 2nd argument, offset is in CX register
  4491                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4492                              <1> 	;	
  4493                              <1> 
  4494 000044A4 E822000000          <1> 	call	seektell
  4495                              <1> 	; AX = u.count
  4496                              <1> 	; BX = *u.fofp
  4497                              <1> 		; jsr r0,seektell / get proper value in u.count
  4498                              <1> 		; add u.base,u.count / add u.base to it
  4499 000044A9 0305[30660000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4500 000044AF 8903                <1> 	mov	[ebx], eax
  4501                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4502 000044B1 E971EDFFFF          <1> 	jmp	sysret
  4503                              <1> 		; br sysret4
  4504                              <1> 
  4505                              <1> systell: ; / get the r/w pointer
  4506                              <1> 	; 03/02/2022
  4507                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4508                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4509                              <1> 	;
  4510                              <1> 	; Retro UNIX 8086 v1 modification:
  4511                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4512                              <1> 	; 	    it returns with error !
  4513                              <1> 	; Inputs: r0 - file descriptor 
  4514                              <1> 	; Outputs: r0 - file r/w pointer
  4515                              <1> 
  4516                              <1> 	;xor	ecx, ecx ; 0
  4517                              <1> 	;mov	edx, 1 ; 05/08/2013
  4518                              <1> 	; 03/02/2022
  4519 000044B6 29D2                <1> 	sub	edx, edx
  4520 000044B8 FEC2                <1> 	inc	dl
  4521                              <1> 	; edx = 1
  4522                              <1> 	;call 	seektell
  4523 000044BA E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4524                              <1> 	;mov	ebx, [u.fofp]
  4525 000044BF 8B03                <1> 	mov	eax, [ebx]
  4526 000044C1 A3[10660000]        <1> 	mov	[u.r0], eax
  4527 000044C6 E95CEDFFFF          <1> 	jmp	sysret
  4528                              <1> 
  4529                              <1> ; Original unix v1 'systell' system call:
  4530                              <1> 		; jsr r0,seektell
  4531                              <1> 		; br error4
  4532                              <1> 
  4533                              <1> seektell:
  4534                              <1> 	; 03/02/2022
  4535                              <1> 	; 03/01/2016
  4536                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4537                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4538                              <1> 	;
  4539                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4540                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4541                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4542                              <1> 	; getf. The i-node is brought into core and then u.count
  4543                              <1> 	; is checked to see it is a 0, 1, or 2.
  4544                              <1> 	; If it is 0 - u.count stays the same
  4545                              <1> 	;          1 - u.count = offset (u.fofp)
  4546                              <1> 	;	   2 - u.count = i.size (size of file)
  4547                              <1> 	; 	 		
  4548                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4549                              <1> 	;	Argument 1, file descriptor is in BX;
  4550                              <1> 	;	Argument 2, offset is in CX;
  4551                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4552                              <1> 	;
  4553                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4554                              <1> 	; call 	arg
  4555                              <1> 	;
  4556                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4557                              <1> 	;
  4558 000044CB 890D[30660000]      <1> 	mov 	[u.base], ecx ; offset
  4559                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4560                              <1> seektell0:
  4561 000044D1 8915[34660000]      <1> 	mov 	[u.count], edx
  4562                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4563                              <1> 	; mov	ax, bx
  4564                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4565                              <1> 			     ; / (index in u.fp list)
  4566                              <1> 	; call	getf
  4567                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4568                              <1> 	; BX = file descriptor (file number)
  4569 000044D7 E8F9FBFFFF          <1> 	call	getf1
  4570                              <1> 	; 03/02/2022
  4571 000044DC 09C0                <1> 	or	eax, eax
  4572                              <1> 	;or	ax, ax ; i-number of the file
  4573                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4574                              <1> 		             ; / put it on the stack
  4575                              <1> 	;jz	error
  4576                              <1> 		; beq error4 / if i-number is 0, not active so error
  4577 000044DE 750F                <1> 	jnz	short seektell1
  4578 000044E0 C705[5F660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4578 000044E8 0000                <1>
  4579 000044EA E918EDFFFF          <1> 	jmp	error
  4580                              <1> seektell1:
  4581                              <1> 	;push	eax
  4582 000044EF 80FC80              <1> 	cmp	ah, 80h
  4583 000044F2 7203                <1> 	jb	short seektell2
  4584                              <1> 		; bgt .+4 / if its positive jump
  4585 000044F4 66F7D8              <1> 	neg	ax
  4586                              <1> 		; neg r1 / if not make it positive
  4587                              <1> seektell2:
  4588 000044F7 E821040000          <1> 	call	iget
  4589                              <1> 		; jsr r0,iget / get its i-node into core
  4590 000044FC 8B1D[20660000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4591 00004502 803D[34660000]01    <1> 	cmp	byte [u.count], 1
  4592                              <1> 		; cmp u.count,$1 / is ptr name =1
  4593 00004509 7705                <1> 	ja	short seektell3
  4594                              <1> 		; blt 2f / no its zero
  4595 0000450B 740A                <1> 	je	short seektell_4
  4596                              <1> 		; beq 1f / yes its 1
  4597 0000450D 31C0                <1> 	xor	eax, eax
  4598                              <1> 	;jmp	short seektell_5
  4599 0000450F C3                  <1> 	retn
  4600                              <1> seektell3:
  4601                              <1> 	; 03/01/2016
  4602                              <1> 	;movzx  eax, word [i.size]
  4603 00004510 66A1[08630000]      <1> 	mov	ax, [i.size]
  4604                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4605                              <1>                                    ; / in file in u.count
  4606                              <1> 	;jmp	short seektell_5
  4607                              <1> 		; br 2f
  4608 00004516 C3                  <1> 	retn
  4609                              <1> seektell_4: ; 1: / ptrname =1
  4610                              <1> 	;mov	ebx, [u.fofp]
  4611 00004517 8B03                <1> 	mov	eax, [ebx]
  4612                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4613                              <1> ;seektell_5: ; 2: / ptrname =0
  4614                              <1> 	;mov	[u.count], eax
  4615                              <1> 	;pop	eax 
  4616                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4617 00004519 C3                  <1> 	retn
  4618                              <1> 		; rts r0
  4619                              <1> 
  4620                              <1> sysintr: ; / set interrupt handling
  4621                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4622                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4623                              <1> 	;
  4624                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4625                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4626                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4627                              <1> 	; If one does the interrupt character in the tty buffer is
  4628                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4629                              <1> 	; 'sysret' is just called.	
  4630                              <1> 	;
  4631                              <1> 	; Calling sequence:
  4632                              <1> 	;	sysintr; arg
  4633                              <1> 	; Argument:
  4634                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4635                              <1> 	;	    - if 1, intterupts cause their normal result
  4636                              <1> 	;		 i.e force an exit.
  4637                              <1> 	;	    - if arg is a location within the program,
  4638                              <1> 	;		control is passed to that location when
  4639                              <1> 	;		an interrupt occurs.	
  4640                              <1> 	; Inputs: -
  4641                              <1> 	; Outputs: -
  4642                              <1> 	; ...............................................................
  4643                              <1> 	;	
  4644                              <1> 	; Retro UNIX 8086 v1 modification: 
  4645                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4646                              <1> 	;	then branches into sysquit.
  4647                              <1> 	;
  4648 0000451A 66891D[4E660000]    <1> 	mov	[u.intr], bx
  4649                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4650                              <1> 		; br 1f / go into quit routine
  4651 00004521 E901EDFFFF          <1> 	jmp	sysret
  4652                              <1> 
  4653                              <1> sysquit:
  4654                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4655                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4656                              <1> 	;
  4657                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4658                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4659                              <1> 	; tty exists. If one does the interrupt character in the tty
  4660                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4661                              <1> 	; 'sysret' is just called.	
  4662                              <1> 	;
  4663                              <1> 	; Calling sequence:
  4664                              <1> 	;	sysquit; arg
  4665                              <1> 	; Argument:
  4666                              <1> 	;	arg - if 0, this call diables quit signals from the
  4667                              <1> 	;		typewriter (ASCII FS)
  4668                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4669                              <1> 	;		cease and a core image to be produced.
  4670                              <1> 	;		 i.e force an exit.
  4671                              <1> 	;	    - if arg is an addres in the program,
  4672                              <1> 	;		a quit causes control to sent to that
  4673                              <1> 	;		location.	
  4674                              <1> 	; Inputs: -
  4675                              <1> 	; Outputs: -
  4676                              <1> 	; ...............................................................
  4677                              <1> 	;	
  4678                              <1> 	; Retro UNIX 8086 v1 modification: 
  4679                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4680                              <1> 	;	then branches into 'sysret'.
  4681                              <1> 	;
  4682 00004526 66891D[50660000]    <1> 	mov	[u.quit], bx
  4683 0000452D E9F5ECFFFF          <1> 	jmp	sysret
  4684                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4685                              <1> 	;1:
  4686                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4687                              <1> 			      ; / to r1
  4688                              <1> 		; beq sysret4 / return to user
  4689                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4690                              <1> 			   ; / in the tty buffer
  4691                              <1> 		; br sysret4 / return to user
  4692                              <1> 
  4693                              <1> syssetuid: ; / set process id
  4694                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4695                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4696                              <1> 	;
  4697                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4698                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4699                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4700                              <1> 	; Only the super user can make this call.	
  4701                              <1> 	;
  4702                              <1> 	; Calling sequence:
  4703                              <1> 	;	syssetuid
  4704                              <1> 	; Arguments: -
  4705                              <1> 	;
  4706                              <1> 	; Inputs: (u.r0) - contains the process id.
  4707                              <1> 	; Outputs: -
  4708                              <1> 	; ...............................................................
  4709                              <1> 	;	
  4710                              <1> 	; Retro UNIX 8086 v1 modification: 
  4711                              <1> 	;       BL contains the (new) user ID of the current process
  4712                              <1> 
  4713                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4714 00004532 3A1D[57660000]      <1> 	cmp	bl, [u.ruid] 
  4715                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4716                              <1> 			       ; / id number
  4717 00004538 741E                <1> 	je	short setuid1
  4718                              <1> 		; beq 1f / yes
  4719 0000453A 803D[56660000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4720                              <1> 		; tstb u.uid / no, is current user the super user?
  4721                              <1> 	;ja	error
  4722                              <1> 		; bne error4 / no, error
  4723 00004541 760F                <1> 	jna	short setuid0
  4724 00004543 C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4724 0000454B 0000                <1>
  4725                              <1> 				; 'permission denied !' error
  4726 0000454D E9B5ECFFFF          <1> 	jmp	error
  4727                              <1> setuid0:
  4728 00004552 881D[57660000]      <1> 	mov	[u.ruid], bl
  4729                              <1> setuid1: ; 1:
  4730 00004558 881D[56660000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4731                              <1> 		; movb r1,u.uid / put process id in u.uid
  4732                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4733 0000455E E9C4ECFFFF          <1> 	jmp	sysret
  4734                              <1> 		; br sysret4 / system return
  4735                              <1> 
  4736                              <1> sysgetuid: ; < get user id >
  4737                              <1> 	; 03/02/2022
  4738                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4739                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4740                              <1> 	;
  4741                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4742                              <1> 	; The real user ID identifies the person who is logged in,
  4743                              <1> 	; in contradistinction to the effective user ID, which
  4744                              <1> 	; determines his access permission at each moment. It is thus
  4745                              <1> 	; useful to programs which operate using the 'set user ID'
  4746                              <1> 	; mode, to find out who invoked them.	
  4747                              <1> 	;
  4748                              <1> 	; Calling sequence:
  4749                              <1> 	;	syssetuid
  4750                              <1> 	; Arguments: -
  4751                              <1> 	;
  4752                              <1> 	; Inputs: -
  4753                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4754                              <1> 	; ...............................................................
  4755                              <1> 	;	
  4756                              <1> 	; Retro UNIX 8086 v1 modification: 
  4757                              <1> 	;       AL contains the real user ID at return.
  4758                              <1> 	;
  4759                              <1> 	;movzx 	eax, byte [u.ruid]
  4760                              <1> 	; 03/03/2022
  4761 00004563 A0[57660000]        <1> 	mov	al, [u.ruid]
  4762 00004568 A3[10660000]        <1> 	mov	[u.r0], eax
  4763                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4764 0000456D E9B5ECFFFF          <1> 	jmp	sysret
  4765                              <1> 		; br sysret4 / systerm return, sysret
  4766                              <1> 
  4767                              <1> anyi: 
  4768                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4769                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4770                              <1> 	;
  4771                              <1> 	; 'anyi' is called if a file deleted while open.
  4772                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4773                              <1> 	;
  4774                              <1> 	; INPUTS ->
  4775                              <1> 	;    r1 - contains an i-number
  4776                              <1> 	;    fsp - start of table containing open files
  4777                              <1> 	;
  4778                              <1> 	; OUTPUTS ->
  4779                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4780                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4781                              <1> 	;    if file not found - bit in i-node map is cleared
  4782                              <1> 	;    			 (i-node is freed)
  4783                              <1> 	;               all blocks related to i-node are freed
  4784                              <1> 	;	        all flags in i-node are cleared
  4785                              <1> 	; ((AX = R1)) input
  4786                              <1> 	;
  4787                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4788                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4789                              <1> 	;
  4790                              <1> 		; / r1 contains an i-number
  4791 00004572 BB[D4630000]        <1> 	mov	ebx, fsp
  4792                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4793                              <1> anyi_1: ; 1:
  4794 00004577 663B03              <1> 	cmp	ax, [ebx]
  4795                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4796 0000457A 7433                <1> 	je	short anyi_3
  4797                              <1> 		; beq 1f / yes, 1f
  4798 0000457C 66F7D8              <1> 	neg	ax
  4799                              <1> 		; neg r1 / no complement r1
  4800 0000457F 663B03              <1> 	cmp	ax, [ebx]
  4801                              <1> 		; cmp r1,(r2) / do they match now?
  4802 00004582 742B                <1> 	je	short anyi_3
  4803                              <1> 		; beq 1f / yes, transfer
  4804                              <1> 		; / i-numbers do not match
  4805 00004584 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4806                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4807                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4808 00004587 81FB[C8650000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4809                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4810                              <1> 				; / are we at last entry in the table
  4811 0000458D 72E8                <1> 	jb	short anyi_1
  4812                              <1> 		; blt 1b / no, check next entries i-number
  4813                              <1> 	;cmp	ax, 32768
  4814 0000458F 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4815                              <1> 		; tst r1 / yes, no match
  4816                              <1> 		; bge .+4
  4817 00004592 7203                <1> 	jb	short anyi_2
  4818 00004594 66F7D8              <1> 	neg	ax
  4819                              <1> 		; neg r1 / make i-number positive
  4820                              <1> anyi_2:	
  4821 00004597 E81A050000          <1> 	call	imap
  4822                              <1> 		; jsr r0,imap / get address of allocation bit 
  4823                              <1> 			    ; / in the i-map in r2
  4824                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4825                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4826                              <1>  	; not	dx
  4827 0000459C F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4828                              <1>         ;and	[ebx], dx
  4829 0000459E 2013                <1> 	and 	[ebx], dl 
  4830                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4831 000045A0 E8A4040000          <1> 	call	itrunc
  4832                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4833 000045A5 66C705[04630000]00- <1>  	mov 	word [i.flgs], 0
  4833 000045AD 00                  <1>
  4834                              <1> 		; clr i.flgs / clear all flags in the i-node
  4835 000045AE C3                  <1> 	retn
  4836                              <1> 		;rts	r0 / return
  4837                              <1> anyi_3: ; 1: / i-numbers match
  4838 000045AF FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4839                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4840                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4841 000045B2 C3                  <1> 	retn
  4842                              <1> 		; rts r0
  2052                                  %include 'u3.s'        ; 10/05/2015
  2053                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2054                              <1> ; Last Modification: 03/02/2022
  2055                              <1> ; ----------------------------------------------------------------------------
  2056                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2057                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2058                              <1> ;
  2059                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2060                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2061                              <1> ; <Bell Laboratories (17/3/1972)>
  2062                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2063                              <1> ;
  2064                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2065                              <1> ;
  2066                              <1> ; ****************************************************************************
  2067                              <1> ; 15/09/2015
  2068                              <1> 
  2069                              <1> tswitch: ; Retro UNIX 386 v1
  2070                              <1> tswap:
  2071                              <1> 	; 01/09/2015
  2072                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2073                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2074                              <1> 	; time out swap, called when a user times out.
  2075                              <1> 	; the user is put on the low priority queue.
  2076                              <1> 	; This is done by making a link from the last user
  2077                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2078                              <1> 	; then he is swapped out.
  2079                              <1> 	;
  2080                              <1> 	; Retro UNIX 386 v1 modification ->
  2081                              <1> 	;       swap (software task switch) is performed by changing
  2082                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2083                              <1> 	;	as in Retro UNIX 8086 v1.
  2084                              <1> 	;
  2085                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2086                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2087                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2088                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2089                              <1> 	;	compatibles was using 1MB segmented memory 
  2090                              <1> 	;	in 8086/8088 times.
  2091                              <1> 	;
  2092                              <1> 	; INPUTS ->
  2093                              <1> 	;    u.uno - users process number
  2094                              <1> 	;    runq+4 - lowest priority queue
  2095                              <1> 	; OUTPUTS ->
  2096                              <1> 	;    r0 - users process number
  2097                              <1> 	;    r2 - lowest priority queue address
  2098                              <1> 	;
  2099                              <1> 	; ((AX = R0, BX = R2)) output
  2100                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2101                              <1> 	;
  2102 000045B3 A0[59660000]        <1> 	mov 	al, [u.uno]
  2103                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2104                              <1> 		; mov  $runq+4,r2 
  2105                              <1> 			; / move lowest priority queue address to r2
  2106 000045B8 E8CD000000          <1>         call 	putlu
  2107                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2108                              <1> 		             ; / u.uno's user
  2109                              <1> 
  2110                              <1> switch: ; Retro UNIX 386 v1
  2111                              <1> swap:
  2112                              <1> 	; 03/02/2022
  2113                              <1> 	; 02/09/2015
  2114                              <1> 	; 01/09/2015
  2115                              <1> 	; 31/08/2015
  2116                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2117                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2118                              <1> 	; 'swap' is routine that controls the swapping of processes
  2119                              <1> 	; in and out of core.
  2120                              <1> 	;
  2121                              <1> 	; Retro UNIX 386 v1 modification ->
  2122                              <1> 	;       swap (software task switch) is performed by changing
  2123                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2124                              <1> 	;	as in Retro UNIX 8086 v1.
  2125                              <1> 	;
  2126                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2127                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2128                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2129                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2130                              <1> 	;	compatibles was using 1MB segmented memory 
  2131                              <1> 	;	in 8086/8088 times.
  2132                              <1> 	;
  2133                              <1> 	; INPUTS ->
  2134                              <1> 	;    runq table - contains processes to run.
  2135                              <1> 	;    p.link - contains next process in line to be run.
  2136                              <1> 	;    u.uno - process number of process in core	
  2137                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2138                              <1> 	; OUTPUTS ->
  2139                              <1> 	;    (original unix v1 -> present process to its disk block)
  2140                              <1> 	;    (original unix v1 -> new process into core -> 
  2141                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2142                              <1> 	;	   for new process)
  2143                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2144                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2145                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2146                              <1> 	;	 for now, it will swap the process if there is not
  2147                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2148                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2149                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2150                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2151                              <1> 	;
  2152                              <1> 	;    u.pri -points to highest priority run Q.
  2153                              <1> 	;    r2 - points to the run queue.
  2154                              <1> 	;    r1 - contains new process number
  2155                              <1> 	;    r0 - points to place in routine or process that called
  2156                              <1> 	;	  swap all user parameters
  2157                              <1> 	;				
  2158                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2159                              <1> 	;
  2160                              <1> swap_0:
  2161                              <1> 		;mov $300,*$ps / processor priority = 6
  2162 000045BD BE[00660000]        <1> 	mov	esi, runq
  2163                              <1> 		; mov $runq,r2 / r2 points to runq table
  2164                              <1> swap_1: ; 1: / search runq table for highest priority process
  2165 000045C2 668B06              <1> 	mov	ax, [esi]
  2166 000045C5 6621C0              <1> 	and 	ax, ax
  2167                              <1>        		; tst (r2)+ / are there any processes to run 
  2168                              <1> 			  ; / in this Q entry
  2169 000045C8 7507                <1> 	jnz	short swap_2
  2170                              <1>        		; bne 1f / yes, process 1f
  2171                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2172                              <1> 			       ; / to end of table
  2173                              <1> 		; bne 1b / if not at end, go back
  2174 000045CA E8E0000000          <1> 	call	idle
  2175                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2176                              <1> 				       ; / all queues are empty
  2177 000045CF EBF1                <1> 	jmp	short swap_1
  2178                              <1> 		; br swap
  2179                              <1> swap_2: ; 1:
  2180 000045D1 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2181                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2182                              <1>  		; mov r2,u.pri / set present user to this run queue
  2183                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2184 000045D4 38E0                <1> 	cmp	al, ah
  2185                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2186                              <1> 			      ; / in this Q to be run
  2187 000045D6 740A                <1> 	je	short swap_3
  2188                              <1>        		; beq 1f / yes
  2189                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2190                              <1> 	;movzx	ebx, al
  2191 000045D8 8AA3[73630000]      <1> 	mov	ah, [ebx+p.link-1] 
  2192 000045DE 8826                <1>        	mov	[esi], ah
  2193                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2194                              <1> 				       ; / in line into run queue
  2195 000045E0 EB05                <1> 	jmp	short swap_4
  2196                              <1>        		; br 2f
  2197                              <1> swap_3: ; 1:
  2198                              <1> 	;xor	dx, dx
  2199                              <1> 	; 03/02/2022
  2200 000045E2 31D2                <1> 	xor	edx, edx
  2201 000045E4 668916              <1> 	mov	[esi], dx
  2202                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2203                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2204                              <1>       ; / in new process if required
  2205                              <1>        		; clr *$ps / clear processor status
  2206 000045E7 8A25[59660000]      <1> 	mov 	ah, [u.uno]
  2207 000045ED 38C4                <1> 	cmp	ah, al
  2208                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2209                              <1> 			      ; / the process in core?
  2210 000045EF 743B                <1>        	je	short swap_8
  2211                              <1>        		; beq 2f / yes, don't have to swap
  2212                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2213                              <1> 			   ; / (address in routine that called swap)
  2214                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2215                              <1> 	; 01/09/2015
  2216                              <1> 	;mov	[u.usp], esp
  2217                              <1>        		; mov sp,u.usp / save stack pointer
  2218                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2219                              <1> 			       ; / to the stack pointer
  2220 000045F1 08E4                <1> 	or	ah, ah
  2221                              <1>        		; tstb u.uno / is the process # = 0
  2222 000045F3 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2223                              <1> 		; beq  1f / yes, kill process by overwriting
  2224                              <1> 	; 02/09/2015
  2225 000045F5 8925[0C660000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2226                              <1> 	;
  2227 000045FB E834000000          <1> 	call	wswap
  2228                              <1> 		;jsr r0,wswap / write out core to disk
  2229                              <1> 	 ; 31/08/2015
  2230                              <1> 	;movzx	ebx, al ; New (running) process number
  2231 00004600 EB1C                <1> 	jmp 	short swap_7
  2232                              <1> swap_6:
  2233                              <1> 	; 31/08/2015
  2234                              <1> 	; Deallocate memory pages belong to the process
  2235                              <1> 	; which is being terminated
  2236                              <1> 	; 14/05/2015 ('sysexit')
  2237                              <1>  	; Deallocate memory pages of the process
  2238                              <1> 	; (Retro UNIX 386 v1 modification !)
  2239                              <1> 	;
  2240                              <1> 	; movzx ebx, al
  2241 00004602 53                  <1> 	push	ebx
  2242 00004603 A1[63660000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2243 00004608 8B1D[67660000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2244 0000460E E81DE0FFFF          <1> 	call	deallocate_page_dir
  2245 00004613 A1[5A660000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2246 00004618 E8ABE0FFFF          <1> 	call	deallocate_page
  2247 0000461D 5B                  <1> 	pop	ebx
  2248                              <1> swap_7: ;1: 
  2249                              <1> 	; 02/09/2015
  2250                              <1> 	; 31/08/2015
  2251                              <1> 	; 14/05/2015
  2252 0000461E C0E302              <1> 	shl	bl, 2 ; * 4 
  2253 00004621 8B83[90630000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2254                              <1> 	;cli
  2255 00004627 E831000000          <1> 	call	rswap
  2256                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2257                              <1> 		; jsr r0,rswap / read new process into core
  2258                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2259                              <1> 			      ; / to his program to its normal
  2260                              <1> 	; 01/09/2015
  2261                              <1> 	;mov	esp, [u.usp]	
  2262                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2263                              <1> 			     ; / new process stack
  2264                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2265                              <1> 			     ; / that just got swapped in, left off.,
  2266                              <1> 			     ; / i.e., transfer control to new process
  2267                              <1> 	;sti
  2268                              <1> swap_8: ;2:
  2269                              <1> 	; RETRO UNIX 8086 v1 modification !
  2270 0000462C C605[4C660000]04    <1> 	mov	byte [u.quant], time_count 
  2271                              <1> 		; movb $30.,uquant / initialize process time quantum
  2272 00004633 C3                  <1> 	retn
  2273                              <1> 		; rts r0 / return
  2274                              <1> 
  2275                              <1> wswap:  ; < swap out, swap to disk >
  2276                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2277                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2278                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2279                              <1> 	; appropriate disk area.
  2280                              <1> 	;
  2281                              <1> 	; Retro UNIX 386 v1 modification ->
  2282                              <1> 	;       User (u) structure content and the user's register content
  2283                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2284                              <1> 	;	saving 'u' structure and user registers for task switching).
  2285                              <1> 	;	u.usp - points to kernel stack address which contains
  2286                              <1> 	;		user's registers while entering system call.  
  2287                              <1> 	;	u.sp  - points to kernel stack address 
  2288                              <1> 	;		to return from system call -for IRET-.
  2289                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2290                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2291                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2292                              <1> 	;
  2293                              <1> 	; Retro UNIX 8086 v1 modification ->
  2294                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2295                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2296                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2297                              <1> 	;	compatibles was using 1MB segmented memory 
  2298                              <1> 	;	in 8086/8088 times.
  2299                              <1> 	;
  2300                              <1> 	; INPUTS ->
  2301                              <1> 	;    u.break - points to end of program
  2302                              <1> 	;    u.usp - stack pointer at the moment of swap
  2303                              <1> 	;    core - beginning of process program		
  2304                              <1> 	;    ecore - end of core 	
  2305                              <1> 	;    user - start of user parameter area		
  2306                              <1> 	;    u.uno - user process number	
  2307                              <1> 	;    p.dska - holds block number of process	
  2308                              <1> 	; OUTPUTS ->
  2309                              <1> 	;    swp I/O queue
  2310                              <1> 	;    p.break - negative word count of process 
  2311                              <1> 	;    r1 - process disk address	
  2312                              <1> 	;    r2 - negative word count
  2313                              <1> 	;
  2314                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2315                              <1> 	;
  2316                              <1> 	; INPUTS ->
  2317                              <1> 	;    u.uno - process number (to be swapped out)
  2318                              <1> 	; OUTPUTS ->
  2319                              <1> 	;    none
  2320                              <1> 	;
  2321                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2322                              <1> 	;
  2323 00004634 8B3D[5A660000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2324 0000463A B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2325 0000463F BE[08660000]        <1> 	mov	esi, user ; active user (u) structure	
  2326 00004644 F3A5                <1> 	rep	movsd
  2327                              <1> 	;
  2328 00004646 8B35[0C660000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2329                              <1> 			     ;      points to user registers)
  2330 0000464C 8B0D[08660000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2331                              <1> 			     ; (for IRET)
  2332                              <1> 			     ; [u.sp] -> EIP (user)
  2333                              <1> 			     ; [u.sp+4]-> CS (user)
  2334                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2335                              <1> 			     ; [u.sp+12] -> ESP (user)
  2336                              <1> 			     ; [u.sp+16] -> SS (user)	
  2337 00004652 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2338 00004654 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2339                              <1> 			     ; (for IRET) 	
  2340 00004657 C1E902              <1> 	shr	ecx, 2	     		
  2341 0000465A F3A5                <1> 	rep	movsd
  2342 0000465C C3                  <1> 	retn
  2343                              <1> 
  2344                              <1> 	; Original UNIX v1 'wswap' routine:
  2345                              <1> 	; wswap:
  2346                              <1> 		; mov *$30,u.emt / determines handling of emts
  2347                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2348                              <1> 				; / illegal instructions
  2349                              <1> 		; mov u.break,r2 / put process program break address in r2
  2350                              <1> 		; inc r2 / add 1 to it 
  2351                              <1> 		; bic $1,r2 / make it even
  2352                              <1> 		; mov r2,u.break / set break to an even location
  2353                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2354                              <1> 			     ; / at moment of swap in r3
  2355                              <1> 		; cmp r2,$core / is u.break less than $core
  2356                              <1> 		; blos 2f / yes
  2357                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2358                              <1>        		; bhis 2f / yes
  2359                              <1> 	; 1:
  2360                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2361                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2362                              <1> 		; bne 1b / no, keep packing
  2363                              <1> 	 	; br 1f / yes
  2364                              <1> 	; 2:
  2365                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2366                              <1> 	; 1:
  2367                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2368                              <1> 			   ; / (user up to end of stack gets written out)
  2369                              <1> 		; neg r2 / make it negative
  2370                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2371                              <1> 		; mov r2,swp+4 / word count
  2372                              <1> 		; movb u.uno,r1 / move user process number to r1
  2373                              <1> 		; asl r1 / x2 for index
  2374                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2375                              <1> 				     ; / into the p.break table
  2376                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2377                              <1> 				    ; /	for process to r1
  2378                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2379                              <1> 			     ; / (block number)
  2380                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2381                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2382                              <1> 	; 1:
  2383                              <1>        		; tstb swp+1 / is lt done writing?
  2384                              <1>        		; bne 1b / no, wait
  2385                              <1> 		; rts r0 / yes, return to swap
  2386                              <1> 
  2387                              <1> rswap:  ; < swap in, swap from disk >
  2388                              <1> 	; 15/09/2015
  2389                              <1> 	; 28/08/2015
  2390                              <1> 	; 14/05/2015
  2391                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2392                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2393                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2394                              <1> 	; from disk into core.
  2395                              <1> 	;
  2396                              <1> 	; Retro UNIX 386 v1 modification ->
  2397                              <1> 	;       User (u) structure content and the user's register content
  2398                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2399                              <1> 	;	saving 'u' structure and user registers for task switching).
  2400                              <1> 	;	u.usp - points to kernel stack address which contains
  2401                              <1> 	;		user's registers while entering system call.  
  2402                              <1> 	;	u.sp  - points to kernel stack address 
  2403                              <1> 	;		to return from system call -for IRET-.
  2404                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2405                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2406                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2407                              <1> 	;
  2408                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2409                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2410                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2411                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2412                              <1> 	;	compatibles was using 1MB segmented memory 
  2413                              <1> 	;	in 8086/8088 times.
  2414                              <1> 	;
  2415                              <1> 	; INPUTS ->
  2416                              <1> 	;    r1 - process number of process to be read in
  2417                              <1> 	;    p.break - negative of word count of process 
  2418                              <1> 	;    p.dska - disk address of the process		
  2419                              <1> 	;    u.emt - determines handling of emt's 	
  2420                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2421                              <1> 	; OUTPUTS ->
  2422                              <1> 	;    8 = (u.ilgins)
  2423                              <1> 	;    24 = (u.emt)
  2424                              <1> 	;    swp - bit 10 is set to indicate read 
  2425                              <1> 	;		(bit 15=0 when reading is done)	
  2426                              <1> 	;    swp+2 - disk block address
  2427                              <1> 	;    swp+4 - negative word count 	
  2428                              <1> 	;      ((swp+6 - address of user structure)) 
  2429                              <1> 	;
  2430                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2431                              <1> 	;
  2432                              <1> 	; INPUTS ->
  2433                              <1> 	;    AL	- new process number (to be swapped in)	 
  2434                              <1> 	; OUTPUTS ->
  2435                              <1> 	;    none
  2436                              <1> 	;
  2437                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2438                              <1> 	;
  2439                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2440 0000465D 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2441 0000465F B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2442 00004664 BF[08660000]        <1> 	mov	edi, user ; active user (u) structure	
  2443 00004669 F3A5                <1> 	rep	movsd
  2444 0000466B 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2445 0000466C 8B3D[0C660000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2446                              <1> 			     ;      points to user registers)
  2447 00004672 8B0D[08660000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2448                              <1> 			     ; (for IRET)
  2449                              <1> 			     ; [u.sp] -> EIP (user)
  2450                              <1> 			     ; [u.sp+4]-> CS (user)
  2451                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2452                              <1> 			     ; [u.sp+12] -> ESP (user)
  2453                              <1> 			     ; [u.sp+16] -> SS (user)		
  2454                              <1> 	; 28/08/2015
  2455 00004678 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2456 0000467A 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2457                              <1> 			     ; (for IRET) 	
  2458 0000467D C1E902              <1> 	shr	ecx, 2	       		
  2459 00004680 F3A5                <1> 	rep	movsd
  2460 00004682 8B25[0C660000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2461 00004688 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2462 00004689 C3                  <1> 	retn
  2463                              <1> 
  2464                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2465                              <1> 	;rswap:
  2466                              <1>        		; asl r1 / process number x2 for index
  2467                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2468                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2469                              <1>        		; bis $2000,swp / read
  2470                              <1>        		; jsr r0,ppoke / read it in 
  2471                              <1> 	; 1:
  2472                              <1>        		; tstb swp+1 / done
  2473                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2474                              <1>        		; mov u.emt,*$30 / yes move these
  2475                              <1>        		; mov u.ilgins,*$10 / back
  2476                              <1>        		; rts r0 / return
  2477                              <1> 
  2478                              <1> 	;unpack: ; / move stack back to its normal place
  2479                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2480                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2481                              <1> 		; blos 2f / yes, return
  2482                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2483                              <1> 			     ; / before swapping
  2484                              <1> 		; bhis 2f / yes, return
  2485                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2486                              <1> 		; add r3,r2
  2487                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2488                              <1> 	; 1:
  2489                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2490                              <1> 		; cmp r2,u.break / in core
  2491                              <1> 		; bne 1b
  2492                              <1> 	; 2:
  2493                              <1>        		; rts r0
  2494                              <1> 
  2495                              <1> putlu: 
  2496                              <1> 	; 12/09/2015
  2497                              <1> 	; 02/09/2015
  2498                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2499                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2500                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2501                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2502                              <1> 	; the last process on the queue to process in r1 by putting
  2503                              <1> 	; the process number in r1 into the last process's link.
  2504                              <1> 	;
  2505                              <1> 	; INPUTS ->
  2506                              <1> 	;    r1 - user process number
  2507                              <1> 	;    r2 - points to lowest priority queue 
  2508                              <1> 	;    p.dska - disk address of the process		
  2509                              <1> 	;    u.emt - determines handling of emt's 	
  2510                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2511                              <1> 	; OUTPUTS ->
  2512                              <1> 	;    r3 - process number of last process on the queue upon
  2513                              <1> 	;	  entering putlu
  2514                              <1> 	;    p.link-1 + r3 - process number in r1
  2515                              <1> 	;    r2 - points to lowest priority queue
  2516                              <1> 	;
  2517                              <1> 	; ((Modified registers: EDX, EBX)) 
  2518                              <1> 	;
  2519                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2520                              <1> 
  2521                              <1> 	; eBX = r2
  2522                              <1> 	; eAX = r1 (AL=r1b)
  2523                              <1> 
  2524 0000468A BB[00660000]        <1> 	mov	ebx, runq
  2525 0000468F 0FB613              <1> 	movzx  	edx, byte [ebx]
  2526 00004692 43                  <1> 	inc	ebx
  2527 00004693 20D2                <1> 	and	dl, dl
  2528                              <1> 		; tstb (r2)+ / is queue empty?
  2529 00004695 740A                <1>        	jz	short putlu_1
  2530                              <1> 		; beq 1f / yes, branch
  2531 00004697 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2532                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2533                              <1> 			     ; / in r3
  2534 00004699 8882[73630000]      <1>        	mov	[edx+p.link-1], al
  2535                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2536                              <1> 			     ; / "last users" link
  2537 0000469F EB03                <1> 	jmp	short putlu_2
  2538                              <1> 		; br 2f /
  2539                              <1> putlu_1: ; 1:
  2540 000046A1 8843FF              <1> 	mov	[ebx-1], al
  2541                              <1>        		; movb r1,-1(r2) / user is only user; 
  2542                              <1> 			    ; / put process no. at beginning and at end
  2543                              <1> putlu_2: ; 2: 
  2544 000046A4 8803                <1> 	mov	[ebx], al
  2545                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2546                              <1> 			     ; / on the queue
  2547 000046A6 88C2                <1> 	mov	dl, al
  2548 000046A8 88B2[73630000]      <1>         mov     [edx+p.link-1], dh ; 0
  2549                              <1> 		; dec r2 / restore r2
  2550 000046AE C3                  <1>         retn
  2551                              <1> 		; rts r0
  2552                              <1> 
  2553                              <1> ;copyz:
  2554                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2555                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2556                              <1> ;       mov     (r0)+,r1
  2557                              <1> ;       mov     (r0)+,r2
  2558                              <1> ;1:
  2559                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2560                              <1> ;       cmp     r1,r2 
  2561                              <1> ;       blo     1b
  2562                              <1> ;       mov     (sp)+,r2 / restore r2
  2563                              <1> ;       mov     (sp)+,r1 / restore r1
  2564                              <1> ;       rts     r0 
  2565                              <1> 
  2566                              <1> idle:
  2567                              <1> 	; 01/09/2015
  2568                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2569                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2570                              <1> 	; (idle & wait loop)
  2571                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2572                              <1> 	; idle procedure!
  2573                              <1>       	;
  2574                              <1>   	; 01/09/2015
  2575 000046AF FB                  <1> 	sti
  2576                              <1>       	; 29/07/2013
  2577 000046B0 F4                  <1>       	hlt
  2578 000046B1 90                  <1>       	nop ; 10/10/2013
  2579 000046B2 90                  <1>       	nop
  2580 000046B3 90                  <1>       	nop
  2581                              <1>       	; 23/10/2013
  2582 000046B4 90                  <1>       	nop
  2583 000046B5 90                  <1>       	nop
  2584 000046B6 90                  <1>       	nop
  2585 000046B7 90                  <1>       	nop
  2586 000046B8 C3                  <1>       	retn      
  2587                              <1> 
  2588                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2589                              <1> 	;clr *$ps / clear ps
  2590                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2591                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2592                              <1> 	;1 / wait for interrupt
  2593                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2594                              <1> 	;mov (sp)+,*$ps
  2595                              <1> 	;rts r0
  2596                              <1> 
  2597                              <1> clear:
  2598                              <1> 	; 03/02/2022
  2599                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2600                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2601                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2602                              <1> 	; on the current device (cdev)
  2603                              <1> 	;	
  2604                              <1> 	; INPUTS ->
  2605                              <1> 	;    r1 - block number of block to be zeroed
  2606                              <1> 	;    cdev - current device number 
  2607                              <1> 	; OUTPUTS ->
  2608                              <1> 	;    a zeroed I/O buffer onto the current device
  2609                              <1> 	;    r1 - points to last entry in the I/O buffer
  2610                              <1> 	;
  2611                              <1> 	; ((AX = R1)) input/output
  2612                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2613                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2614                              <1> 
  2615 000046B9 E87C0E0000          <1> 	call 	wslot
  2616                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2617                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2618 000046BE 89DF                <1> 	mov	edi, ebx ; r5
  2619 000046C0 89C2                <1> 	mov	edx, eax
  2620 000046C2 B980000000          <1> 	mov	ecx, 128
  2621                              <1> 		; mov $256.,r3
  2622 000046C7 31C0                <1> 	xor	eax, eax
  2623 000046C9 F3AB                <1> 	rep	stosd
  2624 000046CB 89D0                <1> 	mov	eax, edx
  2625                              <1> ; 1: 
  2626                              <1>        		; clr (r5)+ / zero data word in buffer
  2627                              <1>        		; dec r3
  2628                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2629                              <1> 	;call	dskwr
  2630                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2631                              <1>                              ; / block specified in r1
  2632                              <1> 	; eAX (r1) = block number
  2633                              <1> 	;retn
  2634                              <1> 		; rts r0
  2635                              <1> 	; 03/02/2022
  2636 000046CD E9750E0000          <1> 	jmp	dskwr
  2053                                  %include 'u4.s'        ; 15/04/2015
  2054                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2055                              <1> ; Last Modification: 26/02/2022
  2056                              <1> ; ----------------------------------------------------------------------------
  2057                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2058                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2059                              <1> ;
  2060                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2061                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2062                              <1> ; <Bell Laboratories (17/3/1972)>
  2063                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2064                              <1> ;
  2065                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2066                              <1> ;
  2067                              <1> ; ****************************************************************************
  2068                              <1> ; 14/10/2015
  2069                              <1> 
  2070                              <1> ;setisp:
  2071                              <1>        ;mov     r1,-(sp)
  2072                              <1>        ;mov     r2,-(sp)
  2073                              <1>        ;mov     r3,-(sp)
  2074                              <1>        ;mov     clockp,-(sp)
  2075                              <1>        ;mov     $s.syst+2,clockp
  2076                              <1>        ;jmp     (r0)
  2077                              <1> 
  2078                              <1> clock: ; / interrupt from 60 cycle clock
  2079                              <1> 	
  2080                              <1> 	; 14/10/2015
  2081                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2082                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2083                              <1> 
  2084                              <1>        ;mov     r0,-(sp) / save r0
  2085                              <1>        ;tst     *$lks / restart clock?
  2086                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2087                              <1>        ;inc     (r0)
  2088                              <1>        ;bne     1f
  2089                              <1>        ;inc     -(r0)
  2090                              <1> ;1:
  2091                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2092                              <1>        ;inc     (r0)
  2093                              <1>        ;bne     1f
  2094                              <1>        ;inc     -(r0)
  2095                              <1> ;1:
  2096                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2097                              <1> 
  2098 000046D2 803D[4C660000]00    <1> 	cmp	byte [u.quant], 0
  2099 000046D9 772C                <1> 	ja	short clk_1
  2100                              <1> 	;
  2101 000046DB 803D[05660000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2102 000046E2 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2103 000046E4 803D[59660000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2104 000046EB 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2105 000046ED 66833D[4E660000]00  <1> 	cmp	word [u.intr], 0
  2106 000046F5 7616                <1> 	jna	short clk_2
  2107                              <1> clk_0:
  2108                              <1> 	; 14/10/2015
  2109 000046F7 FE05[05660000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2110 000046FD 58                  <1> 	pop	eax ; return address to the timer interrupt
  2111                              <1> 	;
  2112 000046FE B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2113                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2114 00004700 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2115                              <1> 	;
  2116 00004702 E97CEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2117                              <1> clk_1:
  2118 00004707 FE0D[4C660000]      <1> 	dec	byte [u.quant]
  2119                              <1> clk_2:
  2120 0000470D C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2121                              <1> 
  2122                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2123                              <1> 
  2124                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2125                              <1>        ;decb    (r0)
  2126                              <1>        ;bge     1f / if less than 0
  2127                              <1>        ;clrb    (r0) / make it 0
  2128                              <1> ;1: / decrement time out counts return now if priority was not 0
  2129                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2130                              <1>        ;bge     2f / yes, check time outs
  2131                              <1>        ;tstb    (r0) / no, user timed out?
  2132                              <1>        ;bne     1f / no
  2133                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2134                              <1>        ;bne     1f / no, 1f
  2135                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2136                              <1>        ;sys     0 / sysrele
  2137                              <1>        ;rti
  2138                              <1> ;2: / priority is high so just decrement time out counts
  2139                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2140                              <1> ;2:
  2141                              <1>        ;tstb    (r0) / is the time out?
  2142                              <1>        ;beq     3f / yes, 3f (get next entry)
  2143                              <1>        ;decb    (r0) / no, decrement the time
  2144                              <1>        ;bne     3f / isit zero now?
  2145                              <1>        ;incb    (r0) / yes, increment the time
  2146                              <1> ;3:
  2147                              <1>        ;inc     r0 / next entry
  2148                              <1>        ;cmp     r0,$touts / end of toutt table?
  2149                              <1>        ;blo     2b / no, check this entry
  2150                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2151                              <1>        ;rti / return from interrupt
  2152                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2153                              <1>        ;mov     (sp)+,r0 / restore r0
  2154                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2155                              <1>        ;jsr     r0,setisp / save registers
  2156                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2157                              <1>                                ;  / the table
  2158                              <1> ;1:
  2159                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2160                              <1>        ;beq     2f / yes
  2161                              <1>        ;decb    toutt(r0) / no, decrement the time
  2162                              <1>        ;bne     2f / is the time 0, now
  2163                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2164                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2165                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2166                              <1> ;2:
  2167                              <1>        ;dec     r0 / set up r0 for next entry
  2168                              <1>        ;bge     1b / finished? , no, go back
  2169                              <1>        ;br      retisp / yes, restore registers and do a rti
  2170                              <1> 
  2171                              <1> ;retisp:
  2172                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2173                              <1>        ;mov     (sp)+,r3
  2174                              <1>        ;mov     (sp)+,r2
  2175                              <1>        ;mov     (sp)+,r1
  2176                              <1>        ;mov     (sp)+,r0
  2177                              <1>        ;rti     / return from interrupt
  2178                              <1> 
  2179                              <1> 
  2180                              <1> wakeup: ; / wakeup processes waiting for an event 
  2181                              <1> 	; / by linking them to the queue
  2182                              <1> 	;
  2183                              <1> 	; 26/02/2022
  2184                              <1> 	; 15/09/2015
  2185                              <1> 	; 29/06/2015
  2186                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2187                              <1> 	;
  2188                              <1> 	; 15/05/2013 - 02/06/2014
  2189                              <1> 	; Retro UNIX 8086 v1 modification !
  2190                              <1> 	; (Process/task switching routine by using
  2191                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2192                              <1> 	;
  2193                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2194                              <1> 	; sleeping in the specified wait channel by creating a link 
  2195                              <1> 	; to it from the last user process on the run queue.
  2196                              <1> 	; If there is no process to wake up, nothing happens.
  2197                              <1> 	;
  2198                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2199                              <1> 	; 'switching' status of the current process (owns current tty)
  2200                              <1> 	; (via alt + function keys) to a process which has highest
  2201                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2202                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2203                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2204                              <1> 	; tty for tty switching by keyboard.)	 
  2205                              <1> 	; 
  2206                              <1> 	; INPUT -> 
  2207                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2208                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2209                              <1> 	;
  2210                              <1> 	; ((modified registers: EAX, EBX))
  2211                              <1> 	;
  2212 0000470E 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2213 00004711 81C3[A8620000]      <1> 	add	ebx, wlist
  2214 00004717 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2215 00004719 20C0                <1> 	and	al, al
  2216 0000471B 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2217                              <1> 	;
  2218 0000471D 30E4                <1> 	xor	ah, ah
  2219 0000471F 8825[4C660000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2220 00004725 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2221                              <1> 	; 15/09/2015
  2222 00004727 0FB6D8              <1> 	movzx	ebx, al
  2223                              <1> 	; 26/02/2022 (p.waitc is not used)
  2224                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2225 0000472A FEC4                <1> 	inc	ah
  2226 0000472C 88A3[83630000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2227                              <1> 	;
  2228 00004732 57                  <1> 	push	edi
  2229 00004733 52                  <1> 	push	edx
  2230 00004734 E851FFFFFF          <1> 	call	putlu
  2231 00004739 5A                  <1> 	pop	edx
  2232 0000473A 5F                  <1> 	pop	edi
  2233                              <1> wa0:
  2234 0000473B C3                  <1> 	retn
  2235                              <1> 
  2236                              <1> sleep: 
  2237                              <1> 	; 26/02/2022
  2238                              <1> 	; 03/02/2022
  2239                              <1> 	; 15/09/2015
  2240                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2241                              <1> 	;
  2242                              <1> 	; 09/05/2013 - 20/03/2014
  2243                              <1> 	;
  2244                              <1> 	; Retro UNIX 8086 v1 modification !
  2245                              <1> 	; (Process/task switching and quit routine by using
  2246                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2247                              <1> 	;
  2248                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2249                              <1> 	; tty and tape output or input becomes available
  2250                              <1> 	; and process is put on waiting channel and swapped out,
  2251                              <1> 	; then -when the tty or tape is ready to write or read-
  2252                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2253                              <1> 	;
  2254                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2255                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2256                              <1> 	; status of the current process also INT 1Ch will count down
  2257                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2258                              <1> 	; to tty buffer of the current process and kernel will get
  2259                              <1> 	; user input by using tty buffer of the current process
  2260                              <1> 	; (instead of standard INT 16h interrupt).
  2261                              <1> 	; TTY output will be redirected to related video page of text mode
  2262                              <1> 	; (INT 10h will be called with different video page depending
  2263                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2264                              <1> 	; pseudo screens.)
  2265                              <1> 	;
  2266                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2267                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2268                              <1> 	; characters/data on serial port(s).
  2269                              <1> 	;
  2270                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2271                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2272                              <1> 	; 
  2273                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2274                              <1> 	;
  2275                              <1> 	;; 05/10/2013
  2276                              <1>         ;10/12/2013
  2277                              <1> 	;cmp   byte [u.uno], 1
  2278                              <1>         ;ja    short sleep0
  2279                              <1> 	;retn
  2280                              <1> 
  2281                              <1> 	; 20/03/2014
  2282                              <1> 	;mov	bx, [runq]
  2283                              <1> 	;cmp	bl, bh
  2284                              <1> 	;jne	short sleep0	
  2285                              <1> 	; 25/02/2014
  2286                              <1> 	;cmp word ptr [runq], 0
  2287                              <1> 	;ja short sleep0	
  2288                              <1> 	;retn
  2289                              <1> sleep0:
  2290                              <1> 	;
  2291 0000473C E849000000          <1> 	call	isintr
  2292                              <1> 	;jnz	sysret
  2293                              <1> 		; / wait for event
  2294                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2295                              <1> 			      ; / or quit from user
  2296                              <1>                		; br 2f / something happened
  2297                              <1> 			      ; / yes, his interrupt so return
  2298                              <1>                      	      ;	/ to user
  2299                              <1> 	; 03/02/2022
  2300 00004741 7405                <1> 	jz	short sleep_2
  2301                              <1> sleep_3:
  2302 00004743 E9DFEAFFFF          <1> 	jmp	sysret
  2303                              <1> sleep_2:
  2304                              <1> 	; 30/06/2015
  2305 00004748 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2306 0000474B 81C3[A8620000]      <1> 	add	ebx, wlist
  2307 00004751 8A03                <1> 	mov	al, [ebx]
  2308 00004753 20C0                <1> 	and	al, al
  2309 00004755 7407                <1> 	jz	short sleep1
  2310 00004757 53                  <1> 	push	ebx
  2311 00004758 E82DFFFFFF          <1> 	call	putlu
  2312 0000475D 5B                  <1> 	pop	ebx
  2313                              <1> sleep1:
  2314 0000475E A0[59660000]        <1> 	mov	al, [u.uno]    
  2315 00004763 8803                <1>   	mov	[ebx], al 	; put the process number
  2316                              <1> 				; in the wait channel
  2317                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2318                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2319                              <1> 				     ; / on the stack
  2320                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2321                              <1> 				     ; / to put to sleep in there
  2322                              <1>         ; 15/09/2015
  2323 00004765 0FB6D8              <1> 	movzx	ebx, al
  2324 00004768 C683[83630000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2325                              <1> 	; 26/02/2022 (p.waitc is not used)
  2326                              <1> 	;inc	ah
  2327                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2328                              <1> 	;
  2329 0000476F 66FF35[F4650000]    <1> 	push    word [cdev]
  2330                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2331 00004776 E842FEFFFF          <1> 	call	swap
  2332                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2333 0000477B 668F05[F4650000]    <1>         pop     word [cdev]
  2334                              <1> 		; mov (sp)+,cdev / restore device
  2335 00004782 E803000000          <1> 	call	isintr
  2336                              <1> 	; 22/09/2013
  2337                              <1> 	;jnz	sysret         
  2338                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2339                              <1>                		; br 2f / yes, return to new user
  2340                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2341                              <1> 				; / originally on the wait channel
  2342                              <1>        		; beq 1f / if 0 branch
  2343                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2344                              <1>        		; mov $300,*$ps / processor priority = 6
  2345                              <1> 		; jsr r0,putlu / create link to old process number
  2346                              <1>        		; clr *$ps / clear the status; process priority = 0
  2347                              <1> 	; 03/02/2022
  2348 00004787 75BA                <1> 	jnz	short sleep_3
  2349                              <1>      ;1:
  2350 00004789 C3                  <1> 	retn
  2351                              <1> 		; rts r0 / return
  2352                              <1>      ;2:
  2353                              <1>         ;;jmp	sysret
  2354                              <1> 		; jmp sysret / return to user
  2355                              <1> 
  2356                              <1> isintr:
  2357                              <1> 	; 03/02/2022
  2358                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2359                              <1> 	;
  2360                              <1> 	; 09/05/2013 - 30/05/2014
  2361                              <1> 	;
  2362                              <1> 	; Retro UNIX 8086 v1 modification !
  2363                              <1> 	; (Process/task switching and quit routine by using
  2364                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2365                              <1> 	;
  2366                              <1> 	; Retro UNIX 8086 v1 modification:
  2367                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2368                              <1> 	;  and there is a 'quit' request by user;
  2369                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2370                              <1> 	;  "nothing to do". (20/10/2013)
  2371                              <1> 	;
  2372                              <1> 	; 20/10/2013
  2373 0000478A 66833D[40660000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2374 00004792 761F                <1> 	jna	short isintr2 ; retn
  2375                              <1> 	; 03/09/2013
  2376                              <1> 	; (nothing to do)
  2377                              <1> 	;retn
  2378                              <1> 	; 22/09/2013
  2379 00004794 66833D[4E660000]00  <1> 	cmp	word [u.intr], 0
  2380 0000479C 7615                <1> 	jna	short isintr2 ; retn
  2381                              <1> 	; 30/05/2014
  2382                              <1> 	;push	ax
  2383                              <1> 	; 03/02/2022
  2384 0000479E 50                  <1> 	push	eax
  2385 0000479F 66A1[50660000]      <1> 	mov	ax, [u.quit]
  2386 000047A5 6609C0              <1> 	or	ax, ax ; 0 ?
  2387 000047A8 7408                <1> 	jz	short isintr1 ; zf = 1
  2388 000047AA 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2389 000047AE 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2390                              <1> 	;xor	ax, ax ; zf = 1
  2391                              <1> 	; 03/02/2022
  2392 000047B0 31C0                <1> 	xor	eax, eax ; zf = 1
  2393                              <1> isintr1:
  2394                              <1> 	;pop	ax
  2395                              <1> 	; 03/02/2022
  2396 000047B2 58                  <1> 	pop	eax
  2397                              <1> isintr2: ; 22/09/2013
  2398                              <1> 	; zf=1 -> nothing to do
  2399 000047B3 C3                  <1> 	retn
  2400                              <1> 
  2401                              <1> 	; UNIX v1 original 'isintr' routine... 
  2402                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2403                              <1>        	;mov     r2,-(sp) / save r2
  2404                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2405                              <1>         ;                 / typewriter
  2406                              <1>        	;beq     1f / if 0, do nothing except skip return
  2407                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2408                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2409                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2410                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2411                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2412                              <1>         ;              / of interrupts
  2413                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2414                              <1>      ;1:
  2415                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2416                              <1>      ;4:
  2417                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2418                              <1>        	;mov     (sp)+,r1
  2419                              <1>        	;rts     r0
  2420                              <1>      ;3: / interrupt char = quit (fs)
  2421                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2422                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2423                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2424                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2425                              <1>      ;1: / find process control tty entry in tty block
  2426                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2427                              <1>        	;beq     1f / block found go to 1f
  2428                              <1>        	;add     $8,r1 / look at next tty block
  2429                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2430                              <1>        	;blo     1b / no
  2431                              <1>        	;br      4b / no process control tty found so go to 4b
  2432                              <1>      ;1:
  2433                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2434                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2435                              <1>         ;                  / identifier
  2436                              <1>        	;inc     0f / increment
  2437                              <1>      ;1:
  2438                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2439                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2440                              <1>         ;             / being typed out after you hit the interrupt
  2441                              <1>         ;             / key
  2442                              <1>        	;br      1b
  2054                                  %include 'u5.s'        ; 03/06/2015
  2055                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2056                              <1> ; Last Modification: 22/04/2022
  2057                              <1> ; ----------------------------------------------------------------------------
  2058                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2059                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2060                              <1> ;
  2061                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2062                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2063                              <1> ; <Bell Laboratories (17/3/1972)>
  2064                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2065                              <1> ;
  2066                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2067                              <1> ;
  2068                              <1> ; ****************************************************************************
  2069                              <1> ; 14/11/2015
  2070                              <1> 
  2071                              <1> mget:
  2072                              <1> 	; 22/04/2022
  2073                              <1> 	; 03/02/2022
  2074                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2075                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2076                              <1> 	;
  2077                              <1> 	; Get existing or (allocate) a new disk block for file
  2078                              <1> 	; 
  2079                              <1> 	; INPUTS ->
  2080                              <1> 	;    u.fofp (file offset pointer)
  2081                              <1> 	;    inode 
  2082                              <1> 	;    u.off (file offset)
  2083                              <1> 	; OUTPUTS ->
  2084                              <1> 	;    r1 (physical block number)
  2085                              <1> 	;    r2, r3, r5 (internal)
  2086                              <1> 	;
  2087                              <1> 	; ((AX = R1)) output
  2088                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2089                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2090                              <1> 
  2091                              <1> 		; mov *u.fofp,mq / file offset in mq
  2092                              <1> 		; clr ac / later to be high sig
  2093                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2094                              <1> 		; mov mq,r2
  2095                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2096                              <1> 		; bne 4f / branch for large file
  2097                              <1> mget_0:	
  2098                              <1> 	; 03/02/2022
  2099 000047B4 29C0                <1> 	sub	eax, eax
  2100 000047B6 29D2                <1> 	sub	edx, edx
  2101 000047B8 29C9                <1> 	sub	ecx, ecx
  2102 000047BA 29DB                <1> 	sub	ebx, ebx
  2103                              <1> 
  2104 000047BC 8B35[20660000]      <1>         mov     esi, [u.fofp]
  2105                              <1>         ;movzx	ebx, byte [esi+1]
  2106                              <1> 	; 03/02/2022
  2107 000047C2 46                  <1> 	inc	esi
  2108 000047C3 8A1E                <1> 	mov	bl, [esi]
  2109                              <1> 
  2110                              <1> 	; BX = r2
  2111                              <1> 	; 03/02/2022
  2112 000047C5 F605[05630000]10    <1> 	test	byte [i.flgs+1], 10h
  2113                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2114                              <1> 			  	     ; is this a large or small file
  2115 000047CC 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2116                              <1> 
  2117 000047CE F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2118                              <1> 		; bit $!17,r2
  2119 000047D1 7525                <1> 	jnz 	short mget_2
  2120                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2121 000047D3 80E30E              <1>         and     bl, 0Eh  
  2122                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2123                              <1> 	; 03/02/2022
  2124 000047D6 668B83[0A630000]    <1> 	mov	ax, [ebx+i.dskp]
  2125                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2126                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2127                              <1> 	; 03/02/2022
  2128 000047DD 09C0                <1> 	or	eax, eax
  2129                              <1> 	;or 	ax, ax
  2130 000047DF 7516                <1> 	jnz 	short mget_1 
  2131                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2132                              <1> 		       ; / for file
  2133 000047E1 E8A6000000          <1> 	call 	alloc
  2134                              <1> 		; jsr r0,alloc / allocate a new block
  2135                              <1>          ; eAX (r1) = Physical block number
  2136 000047E6 668983[0A630000]    <1> 	mov 	[ebx+i.dskp], ax
  2137                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2138 000047ED E835020000          <1> 	call 	setimod	
  2139                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2140 000047F2 E8C2FEFFFF          <1> 	call	clear
  2141                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2142                              <1> mget_1: ; 2:
  2143                              <1>         ; eAX (r1) = Physical block number
  2144 000047F7 C3                  <1> 	retn 
  2145                              <1> 		; rts r0
  2146                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2147 000047F8 E88F000000          <1> 	call 	alloc
  2148                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2149                              <1> 	                     ; / block number in r1
  2150                              <1>         ; eAX (r1) = Physical block number
  2151 000047FD E8380D0000          <1> 	call 	wslot
  2152                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2153                              <1> 			     ; / first data word in buffer
  2154                              <1>         ; 03/02/2022
  2155 00004802 31C9                <1> 	xor	ecx, ecx
  2156 00004804 B108                <1> 	mov	cl, 8
  2157                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2158                              <1> 		   ; into new indirect block area for the new
  2159                              <1> 		   ; large file		
  2160 00004806 89DF                <1> 	mov 	edi, ebx ; r5
  2161 00004808 BE[0A630000]        <1> 	mov 	esi, i.dskp 
  2162                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2163                              <1> 			   ; / block pointers
  2164                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2165                              <1> 			  ; / large file
  2166                              <1> 	; 22/04/2022
  2167 0000480D 50                  <1> 	push	eax ; * ; bugfix
  2168                              <1> 
  2169                              <1> 	;xor 	ax, ax ; mov ax, 0
  2170                              <1> 	; 03/02/2022
  2171 0000480E 31C0                <1> 	xor	eax, eax
  2172                              <1> mget_3: ;1:
  2173 00004810 66A5                <1> 	movsw
  2174                              <1> 		; mov (r2),(r5)+
  2175 00004812 668946FE            <1> 	mov 	[esi-2], ax
  2176                              <1> 		; clr (r2)+
  2177 00004816 E2F8                <1> 	loop	mget_3 ; 1b
  2178                              <1> 		; dec r3
  2179                              <1> 		; bgt 1b
  2180                              <1> 
  2181 00004818 B1F8                <1> 	mov 	cl, 256-8
  2182                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2183                              <1> mget_4:	; 1
  2184 0000481A F366AB              <1> 	rep 	stosw
  2185                              <1> 		; clr (r5)+
  2186                              <1> 		; dec r3
  2187                              <1> 		; bgt 1b
  2188                              <1> 	
  2189                              <1> 	; 22/04/2022
  2190                              <1> 	;pop	eax ; * ; bugfix
  2191                              <1> 
  2192                              <1> 	; 24/03/2013
  2193                              <1>         ; AX (r1) = Physical block number
  2194 0000481D E8250D0000          <1> 	call	dskwr
  2195                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2196                              <1> 
  2197                              <1> 	; 22/04/2022
  2198 00004822 58                  <1> 	pop	eax ; * ; bugfix
  2199                              <1> 
  2200                              <1>         ; eAX (r1) = Physical block number
  2201 00004823 66A3[0A630000]      <1> 	mov 	[i.dskp], ax
  2202                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2203                              <1> 	; 03/02/2022
  2204 00004829 800D[05630000]10    <1> 	or	byte [i.flgs+1], 10h
  2205                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2206                              <1> 		; bis $10000,i.flgs / set large file bit 
  2207                              <1> 				  ; / in i.flgs word of i-node
  2208 00004830 E8F2010000          <1> 	call	setimod
  2209                              <1> 		; jsr r0,setimod / set i-node modified flag
  2210 00004835 E97AFFFFFF          <1>         jmp     mget_0 
  2211                              <1> 		; br mget
  2212                              <1> 
  2213                              <1> mget_5:  ; 4 ; large file
  2214                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2215                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2216                              <1> 			    ; / in indirect block
  2217                              <1> 		; mov r2,-(sp) / save on stack (*)
  2218                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2219                              <1>        		          ; / indirect block
  2220                              <1> 		; bic $!16,r2
  2221 0000483A 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2222 0000483D 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2223                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2224                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2225                              <1> 	; There is always 1 indirect block for this file system
  2226                              <1> 	; 03/02/2022
  2227 0000483E 66A1[0A630000]      <1> 	mov	ax, [i.dskp]
  2228                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2229                              <1> 		; mov i.dskp(r2),r1
  2230                              <1> 	; 03/02/2022
  2231 00004844 09C0                <1> 	or	eax, eax
  2232                              <1> 	;or 	ax, ax ; R1
  2233 00004846 7515                <1> 	jnz 	short mget_6 ; 2f
  2234                              <1> 		; bne 2f / if no indirect block exists
  2235 00004848 E83F000000          <1> 	call 	alloc
  2236                              <1> 		; jsr r0,alloc / allocate a new block
  2237 0000484D 66A3[0A630000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2238                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2239 00004853 E8CF010000          <1> 	call 	setimod
  2240                              <1> 		; jsr r0,setimod / set i-node modified byte
  2241                              <1> 	; eAX = new block number
  2242 00004858 E85CFEFFFF          <1> 	call 	clear
  2243                              <1> 		; jsr r0,clear / clear new block
  2244                              <1> mget_6: ;2
  2245                              <1> 	; 05/03/2013
  2246                              <1> 	; eAX = r1, physical block number (of indirect block)
  2247 0000485D E8740C0000          <1> 	call 	dskrd ; read indirect block
  2248                              <1> 		; jsr r0,dskrd / read in indirect block
  2249 00004862 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2250                              <1> 		; mov (sp)+,r2 / get offset
  2251                              <1> 	; eAX = r1, physical block number (of indirect block)
  2252 00004863 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2253                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2254                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2255 00004864 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2256                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2257                              <1> 	                  ; / points to location of inter
  2258                              <1> 	; 03/02/2022
  2259 00004866 668B03              <1> 	mov	ax, [ebx]
  2260                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2261                              <1> 			      ; in file sought in R1 (AX)
  2262                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2263                              <1> 	               	    ; / sought in r1
  2264                              <1> 	; 03/02/2022
  2265 00004869 09C0                <1> 	or	eax, eax
  2266                              <1> 	;or 	ax, ax
  2267 0000486B 751D                <1>         jnz 	short mget_7 ; 2f
  2268                              <1> 		; bne 2f / if no block exists 
  2269 0000486D E81A000000          <1> 	call 	alloc
  2270                              <1> 		; jsr r0,alloc / allocate a new block
  2271 00004872 668903              <1> 	mov 	[ebx], ax ; R1
  2272                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2273                              <1> 	                    ; / indirect block
  2274 00004875 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2275                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2276 00004876 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2277 00004877 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2278 00004878 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2279                              <1> 		; mov (r2),-(sp) / save block number of new block
  2280                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2281 0000487A E8BB0C0000          <1> 	call 	wslot
  2282                              <1> 		; jsr r0,wslot
  2283                              <1>         ; eAX (r1) = physical block number
  2284                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2285 0000487F E8C30C0000          <1> 	call 	dskwr
  2286                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2287                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2288                              <1> 			     ; / back out on disk
  2289 00004884 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2290                              <1> 		; mov (sp),r1 / restore block number of new block	
  2291                              <1> 	; eAX (r1) = physical block number of new block
  2292 00004885 E82FFEFFFF          <1> 	call 	clear
  2293                              <1> 		; jsr r0,clear / clear new block	
  2294                              <1> mget_7: ; 2
  2295 0000488A 5A                  <1> 	pop 	edx ; **
  2296                              <1> 		; tst (sp)+ / bump stack pointer
  2297                              <1> 	; eAX (r1) = Block number of new block
  2298 0000488B C3                  <1> 	retn
  2299                              <1> 		; rts r0
  2300                              <1> 
  2301                              <1> alloc:
  2302                              <1> 	; 03/02/2022
  2303                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2304                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2305                              <1> 	;
  2306                              <1> 	; get a free block and 
  2307                              <1> 	; set the corresponding bit in the free storage map
  2308                              <1> 	; 
  2309                              <1> 	; INPUTS ->
  2310                              <1> 	;    cdev (current device)
  2311                              <1> 	;    r2 
  2312                              <1> 	;    r3
  2313                              <1> 	; OUTPUTS ->
  2314                              <1> 	;    r1 (physical block number of block assigned)
  2315                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2316                              <1> 	;
  2317                              <1> 	; ((AX = R1)) output
  2318                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2319                              <1>         ;    ((Modified registers: DX, CX))  
  2320                              <1> 
  2321                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2322                              <1> 		;mov r3,-(sp)
  2323                              <1> 	;push 	ecx
  2324 0000488C 53                  <1> 	push 	ebx ; R2
  2325                              <1> 	;push 	edx ; R3
  2326 0000488D BB[D8760000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2327                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2328 00004892 803D[F4650000]00    <1> 	cmp 	byte [cdev], 0
  2329                              <1> 		; tst cdev
  2330 00004899 7605                <1> 	jna	short alloc_1
  2331                              <1> 		; beq 1f / drum is device
  2332 0000489B BB[E0780000]        <1> 	mov	ebx, mount
  2333                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2334                              <1> 			      ; / free storage map
  2335                              <1> alloc_1: ; 1
  2336                              <1> 	; 03/02/2022
  2337                              <1> 	;sub	ecx, ecx
  2338                              <1> 	;sub	edx, edx
  2339                              <1> 	;sub	eax, eax
  2340                              <1> 
  2341 000048A0 668B0B              <1>         mov	cx, [ebx]
  2342                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2343                              <1> 			     ; / storage map
  2344                              <1> 	; 03/02/2022
  2345 000048A3 C1E103              <1> 	shl	ecx, 3
  2346                              <1> 	;shl	cx, 3
  2347                              <1> 		; asl r1 / multiply r1 by eight gives 
  2348                              <1> 		; number of blocks in device
  2349                              <1> 		; asl r1
  2350                              <1> 		; asl r1
  2351                              <1> 	;;push	cx ;; 01/08/2013
  2352                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2353 000048A6 31C0                <1> 	xor 	eax, eax ; 0
  2354                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2355                              <1> alloc_2: ; 1
  2356 000048A8 43                  <1> 	inc 	ebx ; 18/8/2012
  2357 000048A9 43                  <1> 	inc 	ebx ; 
  2358 000048AA 668B13              <1> 	mov 	dx, [ebx]
  2359                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2360                              <1> 	; 03/02/2022
  2361 000048AD 09D2                <1> 	or	edx, edx
  2362                              <1> 	;or 	dx, dx
  2363 000048AF 750D                <1> 	jnz 	short alloc_3 ; 1f
  2364                              <1> 		; bne 1f / branch if any free blocks in this word	
  2365 000048B1 6683C010            <1> 	add 	ax, 16
  2366                              <1> 		; add $16.,r1
  2367                              <1> 	; 03/02/2022
  2368 000048B5 39C8                <1> 	cmp	eax, ecx
  2369                              <1> 	;cmp 	ax, cx    
  2370                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2371 000048B7 72EF                <1> 	jb 	short alloc_2
  2372                              <1> 		; blo 1b
  2373                              <1> 	; 14/11/2015
  2374                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2375                              <1> 	;	because of a (DMA or another) r/w error, 
  2376                              <1> 	;	we will be here, at 'jmp panic' code address,
  2377                              <1> 	;	even if the (disk) file system space is not full !!!
  2378                              <1> 	;	(cx = 0)	
  2379                              <1> 	;
  2380 000048B9 E908E2FFFF          <1> 	jmp     panic 
  2381                              <1> 		; jmp panic / found no free storage
  2382                              <1> alloc_3: ; 1
  2383                              <1> 	; 03/02/2022
  2384 000048BE D1EA                <1> 	shr	edx, 1
  2385                              <1> 	;shr	dx, 1
  2386                              <1> 		; asr r3 / find a free block
  2387 000048C0 7203                <1> 	jc	short alloc_4 ; 1f
  2388                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2389                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2390                              <1> 	; 03/02/2022
  2391 000048C2 40                  <1> 	inc	eax
  2392                              <1> 	;inc	ax
  2393                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2394 000048C3 EBF9                <1> 	jmp 	short alloc_3
  2395                              <1> 		; br 1b
  2396                              <1> alloc_4: ; 1:
  2397                              <1> 	;; pop cx ;; 01/08/2013
  2398                              <1> 		; tst (sp)+ / bump sp
  2399                              <1> 	; 02/04/2013 
  2400 000048C5 E829000000          <1> 	call	free3
  2401                              <1> 		; jsr r0,3f / have found a free block
  2402                              <1> 	; 21/8/2012
  2403 000048CA 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2404 000048CD 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2405                              <1> 		; bic r3,(r2) / set bit for this block 
  2406                              <1> 		            ; / i.e. assign block
  2407                              <1> 		; br 2f
  2408 000048D0 EB09                <1> 	jmp 	short alloc_5
  2409                              <1> 
  2410                              <1> free:
  2411                              <1> 	; 03/02/2022
  2412                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2413                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2414                              <1> 	;
  2415                              <1> 	; calculates byte address and bit position for given block number
  2416                              <1> 	; then sets the corresponding bit in the free storage map
  2417                              <1> 	; 
  2418                              <1> 	; INPUTS ->
  2419                              <1> 	;    r1 - block number for a block structured device
  2420                              <1> 	;    cdev - current device 
  2421                              <1> 	; OUTPUTS ->
  2422                              <1> 	;    free storage map is updated
  2423                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2424                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2425                              <1> 	;
  2426                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2427                              <1>         ;  ((Modified registers: DX, CX))  
  2428                              <1> 
  2429                              <1> 		;mov r2,-(sp) / save r2, r3
  2430                              <1> 		;mov r3,-(sp)
  2431                              <1> 	;push 	ecx
  2432 000048D2 53                  <1> 	push 	ebx ; R2
  2433                              <1> 	;push 	edx ; R3 
  2434                              <1> 
  2435 000048D3 E81B000000          <1>         call    free3
  2436                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2437                              <1> 				 ; / in free storage map for block
  2438 000048D8 660913              <1> 	or 	[ebx], dx  
  2439                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2440                              <1> 			    ;  / indicates free block	
  2441                              <1> 	; 0 -> allocated, 1 -> free
  2442                              <1> 
  2443                              <1> alloc_5:
  2444                              <1> 	; 07/04/2013
  2445                              <1> free_1: ; 2:
  2446                              <1> 	;pop 	edx
  2447                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2448 000048DB 5B                  <1> 	pop	ebx
  2449                              <1> 		; mov (sp)+,r2
  2450                              <1> 	; pop	ecx
  2451 000048DC 803D[F4650000]00    <1> 	cmp 	byte [cdev], 0
  2452                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2453                              <1> 			 ; / cdev = 1, mountable device
  2454 000048E3 7707                <1> 	ja	short alloc_6 ; 1f
  2455                              <1> 		; bne 1f
  2456                              <1> 	;mov	byte [smod], 1
  2457 000048E5 FE05[03660000]      <1> 	inc 	byte [smod]
  2458                              <1> 		; incb smod / set super block modified for drum
  2459                              <1> 	; eAX (r1) = block number
  2460 000048EB C3                  <1> 	retn
  2461                              <1> 		; rts r0
  2462                              <1> free_2:
  2463                              <1> alloc_6: ; 1:
  2464                              <1> 	;mov 	byte [mmod], 1
  2465 000048EC FE05[04660000]      <1> 	inc 	byte [mmod]
  2466                              <1> 		; incb	mmod 
  2467                              <1> 		  ; / set super block modified for mountable device
  2468                              <1> 	; eAX (r1) = block number
  2469 000048F2 C3                  <1> 	retn	
  2470                              <1> 		; rts r0
  2471                              <1> free3:
  2472                              <1> 	; 03/02/2022
  2473                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2474                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2475                              <1> 	;
  2476                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2477                              <1> 	; 
  2478                              <1> alloc_free_3: ; 3
  2479                              <1> 	;mov 	dx, 1
  2480                              <1> 	; 03/02/2022
  2481 000048F3 31D2                <1> 	xor	edx, edx
  2482 000048F5 42                  <1> 	inc	edx
  2483                              <1> 	; edx = 1
  2484 000048F6 88C1                <1> 	mov 	cl, al
  2485                              <1> 		; mov r1,r2 / block number, k, = 1		
  2486 000048F8 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2487                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2488 000048FB 7402                <1> 	jz 	short free4
  2489                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2490                              <1> 			       ; / (k) mod 8
  2491                              <1> 	;shl 	dx, cl
  2492                              <1> 	; 03/02/2022
  2493 000048FD D3E2                <1> 	shl	edx, cl
  2494                              <1> free4:
  2495 000048FF 0FB7D8              <1> 	movzx 	ebx, ax
  2496                              <1> 		; mov r1,r2 / divide block number by 16
  2497                              <1> 	; 03/02/2022
  2498 00004902 C1EB04              <1> 	shr	ebx, 4
  2499                              <1> 	;shr 	bx, 4
  2500                              <1> 		; asr r2
  2501                              <1> 		; asr r2
  2502                              <1> 		; asr r2
  2503                              <1> 		; asr r2
  2504                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2505                              <1> 		       ; / bit for block is in lower half of word
  2506                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2507                              <1> 		        ; / storage map
  2508                              <1> alloc_free_4: ; 1
  2509                              <1> 	; 03/02/2022
  2510 00004905 D1E3                <1> 	shl	ebx, 1
  2511                              <1> 	;shl 	bx, 1
  2512                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2513 00004907 81C3[DA760000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2514                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2515                              <1> 	    		        ; / with block bit in it 	
  2516 0000490D 803D[F4650000]00    <1> 	cmp	byte [cdev], 0
  2517                              <1> 		; tst cdev
  2518 00004914 7606                <1> 	jna	short alloc_free_5
  2519                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2520 00004916 81C308020000        <1> 	add	ebx, mount - systm
  2521                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2522                              <1> 				    ; / mountable device with bit of block to be
  2523                              <1> 				    ; / freed
  2524                              <1> alloc_free_5: ; 1 
  2525 0000491C C3                  <1> 	retn
  2526                              <1> 		; rts r0 / return to 'free'
  2527                              <1> 	      ; 2
  2528                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2529                              <1> 	
  2530                              <1> iget:
  2531                              <1> 	; 03/02/2022
  2532                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2533                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2534                              <1> 	;
  2535                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2536                              <1> 	;
  2537                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2538                              <1> 	; 
  2539                              <1> 	; INPUTS ->
  2540                              <1> 	;    ii - current i-number, rootdir
  2541                              <1> 	;    cdev - new i-node device
  2542                              <1> 	;    idev - current i-node device
  2543                              <1> 	;    imod - current i-node modified flag
  2544                              <1> 	;    mnti - cross device file i-number
  2545                              <1> 	;    r1 - i-numbe rof new i-node
  2546                              <1> 	;    mntd - mountable device number		
  2547                              <1> 	; 	 
  2548                              <1> 	; OUTPUTS ->
  2549                              <1> 	;    cdev, idev, imod, ii, r1
  2550                              <1> 	;
  2551                              <1> 	; ((AX = R1)) input/output
  2552                              <1> 	;
  2553                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2554                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2555                              <1> 
  2556 0000491D 8A15[F4650000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2557 00004923 8A35[F2650000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2558                              <1> 	;
  2559 00004929 663B05[F0650000]    <1> 	cmp 	ax, [ii]
  2560                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2561 00004930 7504                <1> 	jne 	short iget_1
  2562                              <1> 		; bne 1f
  2563 00004932 38F2                <1> 	cmp	dl, dh
  2564                              <1> 		; cmp idev,cdev
  2565                              <1> 			  ; / is device number of i-node = current device
  2566 00004934 7472                <1>         je      short iget_5
  2567                              <1> 		; beq 2f
  2568                              <1> iget_1: ; 1:
  2569 00004936 30DB                <1> 	xor	bl, bl
  2570 00004938 381D[02660000]      <1> 	cmp	[imod], bl ; 0	
  2571                              <1> 		; tstb imod / has i-node of current file
  2572                              <1> 			  ; / been modified i.e., imod set
  2573 0000493E 7629                <1> 	jna	short iget_2
  2574                              <1> 		; beq 1f
  2575 00004940 881D[02660000]      <1> 	mov	[imod], bl ; 0
  2576                              <1> 		;  clrb	imod / if it has, 
  2577                              <1> 			   ; / we must write the new i-node out on disk
  2578                              <1> 	; 03/02/2022
  2579 00004946 50                  <1> 	push	eax ; *
  2580                              <1> 	;push	ax
  2581                              <1> 		; mov r1,-(sp)
  2582                              <1> 	;mov	dl, [cdev]
  2583 00004947 52                  <1> 	push	edx ; **
  2584                              <1> 	;push	dx
  2585                              <1> 		; mov cdev,-(sp)
  2586 00004948 66A1[F0650000]      <1> 	mov	ax, [ii]
  2587                              <1> 		; mov ii,r1
  2588                              <1> 	;mov	dh, [idev]
  2589 0000494E 8835[F4650000]      <1> 	mov	[cdev], dh
  2590                              <1> 		; mov idev,cdev
  2591 00004954 FEC3                <1> 	inc	bl ; 1
  2592                              <1> 	; 31/07/2013
  2593 00004956 881D[8C660000]      <1> 	mov     [rw], bl ; 1 == write 
  2594                              <1> 	;;28/07/2013 rw -> u.rw
  2595                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2596 0000495C E848000000          <1> 	call	icalc
  2597                              <1> 		; jsr r0,icalc; 1
  2598                              <1> 	;pop	dx
  2599                              <1> 	; 03/02/2022
  2600 00004961 5A                  <1> 	pop	edx ; **
  2601 00004962 8815[F4650000]      <1> 	mov	[cdev], dl
  2602                              <1> 		; mov (sp)+,cdev
  2603                              <1> 	; 03/02/2022
  2604 00004968 58                  <1> 	pop	eax ; *
  2605                              <1> 	;pop	ax
  2606                              <1> 		; mov (sp)+,r1
  2607                              <1> iget_2: ; 1:
  2608 00004969 6621C0              <1> 	and	ax, ax
  2609                              <1> 		; tst r1 / is new i-number non zero
  2610 0000496C 7434                <1> 	jz	short iget_4 ; 2f
  2611                              <1> 		; beq 2f / branch if r1=0
  2612                              <1> 
  2613                              <1> 	;mov 	dl, [cdev]
  2614 0000496E 08D2                <1> 	or	dl, dl
  2615                              <1> 		; tst cdev / is the current device number non zero
  2616                              <1> 			 ; / (i.e., device =/ drum)
  2617 00004970 7517                <1> 	jnz	short iget_3 ;  1f
  2618                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2619 00004972 663B05[F8650000]    <1> 	cmp	ax, [mnti]			
  2620                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2621                              <1> 			    ; / file (root directory of mounted device)
  2622 00004979 750E                <1> 	jne	short iget_3 ; 1f
  2623                              <1> 		; bne 1f
  2624                              <1>         ;mov    bl, [mntd]
  2625 0000497B FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2626 0000497D 8815[F4650000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2627                              <1> 		; mov mntd,cdev / make mounted device the current device
  2628 00004983 66A1[FE650000]      <1> 	mov	ax, [rootdir]
  2629                              <1> 		; mov rootdir,r1
  2630                              <1> iget_3: ; 1:
  2631 00004989 66A3[F0650000]      <1> 	mov	[ii], ax
  2632                              <1> 		; mov r1,ii
  2633 0000498F 8815[F2650000]      <1> 	mov	[idev], dl ; cdev
  2634                              <1> 		; mov cdev,idev
  2635 00004995 30DB                <1> 	xor	bl, bl
  2636                              <1>         ; 31/07/2013
  2637 00004997 881D[8C660000]      <1> 	mov     [rw], bl ; 0 == read 
  2638                              <1> 	;;28/07/2013 rw -> u.rw       
  2639                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2640 0000499D E807000000          <1> 	call	icalc
  2641                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2642                              <1> iget_4: ; 2:
  2643 000049A2 66A1[F0650000]      <1> 	mov	ax, [ii]
  2644                              <1> 		; mov ii,r1
  2645                              <1> iget_5:
  2646 000049A8 C3                  <1> 	retn
  2647                              <1> 		; rts r0
  2648                              <1> 
  2649                              <1> icalc:
  2650                              <1> 	; 04/04/2022 (47->31)
  2651                              <1> 	;	(Inode Table/List Address modification)
  2652                              <1> 	; 03/02/2022
  2653                              <1> 	; 02/07/2015
  2654                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2655                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2656                              <1> 	;
  2657                              <1> 	; calculate physical block number from i-number then
  2658                              <1> 	; read or write that block
  2659                              <1> 	;
  2660                              <1> 	; 'icalc' is called from 'iget'
  2661                              <1> 	;
  2662                              <1> 	; for original unix v1:
  2663                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2664                              <1>        	; / (i+31.) mod 16. bytes from its start
  2665                              <1> 	;
  2666                              <1> 	; for retro unix 8086 v1:
  2667                              <1> 	;  i-node is located in block (i+47)/16 and
  2668                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2669                              <1> 	;
  2670                              <1> 	; INPUTS ->
  2671                              <1> 	;    r1 - i-number of i-node
  2672                              <1> 	; 	 
  2673                              <1> 	; OUTPUTS ->
  2674                              <1> 	;    inode r/w
  2675                              <1> 	;
  2676                              <1> 	; ((AX = R1)) input
  2677                              <1> 	;
  2678                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2679                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2680                              <1> 	;
  2681 000049A9 0FB7D0              <1> 	movzx	edx, ax	
  2682                              <1> 	;add	dx, 47
  2683                              <1> 	; 04/04/2022
  2684 000049AC 6683C21F            <1> 	add	dx, 31
  2685 000049B0 89D0                <1> 	mov	eax, edx
  2686                              <1> 	;;add	ax, 47	; add 47 to inode number
  2687                              <1> 	;add	ax, 31
  2688                              <1> 		; add $31.,r1 / add 31. to i-number
  2689 000049B2 50                  <1> 	push	eax
  2690                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2691                              <1> 	; 03/02/2022
  2692 000049B3 C1E804              <1> 	shr	eax, 4
  2693                              <1> 	;shr 	ax, 4
  2694                              <1> 		; asr r1 / divide by 16.
  2695                              <1> 		; asr r1
  2696                              <1> 		; asr r1
  2697                              <1> 		; asr r1 / r1 contains block number of block
  2698                              <1> 		       ; / in which i-node exists
  2699 000049B6 E81B0B0000          <1> 	call	dskrd
  2700                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2701                              <1> 	; 31/07/2013
  2702 000049BB 803D[8C660000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2703                              <1> 	;; 28/07/2013 rw -> u.rw
  2704                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2705                              <1> 		; tst (r0)
  2706 000049C2 7605                <1> 	jna	short icalc_1
  2707                              <1> 		; beq 1f / branch to wslot when argument
  2708                              <1> 		       ; / in icalc call = 1
  2709                              <1> 	; eAX = r1 = block number
  2710 000049C4 E8710B0000          <1> 	call	wslot
  2711                              <1> 		; jsr r0,wslot / set up data buffer for write
  2712                              <1> 			     ; / (will be same buffer as dskrd got)
  2713                              <1> 	; eBX = r5 points to first word in data area for this block
  2714                              <1> icalc_1: ; 1:
  2715 000049C9 5A                  <1> 	pop	edx 
  2716 000049CA 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2717                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2718                              <1> 			      ; / gives (i+31.) mod 16
  2719 000049CD C1E205              <1> 	shl 	edx, 5
  2720                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2721 000049D0 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2722 000049D2 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2723                              <1>           	; eSI (r5) points to first word in i-node i.	
  2724                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2725                              <1> 			     ; / 32.*(i+31.)mod16
  2726                              <1> 		; mov $5,lsh / for i-node i.
  2727                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2728 000049D4 BF[04630000]        <1> 	mov	edi, inode
  2729                              <1> 		; mov $inode,r1 / inode is address of first word 
  2730                              <1> 			      ; / of current i-node
  2731                              <1> 	; 03/02/2022
  2732 000049D9 29C9                <1> 	sub	ecx, ecx
  2733 000049DB B108                <1> 	mov	cl, 8 
  2734                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2735                              <1> 		; mov $16.,r3
  2736                              <1>         ; 31/07/2013
  2737 000049DD 382D[8C660000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2738                              <1>        ;;28/07/2013 rw -> u.rw                 
  2739                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2740                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2741 000049E3 7609                <1> 	jna	short icalc_3
  2742                              <1> 		; beq 2f / r0 now contains proper return address 
  2743                              <1> 		       ; / for rts r0
  2744                              <1> icalc_2: ; 1:
  2745 000049E5 87F7                <1> 	xchg 	esi, edi
  2746                              <1> 	; overwrite old i-node (in buffer to be written)
  2747 000049E7 F3A5                <1> 	rep 	movsd
  2748                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2749                              <1> 		; dec r3
  2750                              <1> 		; bgt 1b
  2751                              <1> 	;call	dskwr
  2752                              <1> 		; jsr r0,dskwr / write inode out on device
  2753                              <1> 	;retn
  2754                              <1> 		; rts r0
  2755                              <1> 	; 03/02/2022
  2756 000049E9 E9590B0000          <1> 	jmp	dskwr
  2757                              <1> icalc_3: ; 2:
  2758                              <1> 	; copy new i-node into inode area of (core) memory
  2759 000049EE F3A5                <1> 	rep 	movsd
  2760                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2761                              <1> 		                ; / "inode" area of core
  2762                              <1> 		; dec r3
  2763                              <1> 		; bgt 2b
  2764 000049F0 C3                  <1> 	retn
  2765                              <1> 		; rts r0
  2766                              <1> 
  2767                              <1> access:
  2768                              <1> 	; 03/02/2022
  2769                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2770                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2771                              <1> 	;
  2772                              <1> 	; check whether user is owner of file or user has read or write
  2773                              <1> 	; permission (based on i.flgs).
  2774                              <1> 	;
  2775                              <1> 	; INPUTS ->
  2776                              <1> 	;    r1 - i-number of file
  2777                              <1> 	;    u.uid
  2778                              <1> 	; arg0 -> (owner flag mask)	 		
  2779                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2780                              <1> 	; OUTPUTS ->
  2781                              <1> 	;    inode (or jump to error)
  2782                              <1> 	;
  2783                              <1> 	; ((AX = R1)) input/output
  2784                              <1> 	;
  2785                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2786                              <1> 	;
  2787                              <1> 
  2788                              <1> 	;push	dx  ; save flags (DL)
  2789                              <1> 	; 03/02/2022
  2790 000049F1 52                  <1> 	push	edx ; save flags (DL)
  2791 000049F2 E826FFFFFF          <1> 	call	iget
  2792                              <1> 		; jsr r0,iget / read in i-node for current directory
  2793                              <1> 			    ; / (i-number passed in r1)
  2794 000049F7 8A0D[04630000]      <1> 	mov	cl, [i.flgs]
  2795                              <1> 		; mov i.flgs,r2
  2796                              <1> 	; 03/02/2022
  2797 000049FD 5A                  <1> 	pop	edx ; restore flags (DL)
  2798                              <1> 	;pop	dx  ; restore flags (DL)
  2799 000049FE 8A35[56660000]      <1> 	mov	dh, [u.uid]
  2800 00004A04 3A35[07630000]      <1> 	cmp	dh, [i.uid]
  2801                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2802 00004A0A 7503                <1> 	jne	short access_1
  2803                              <1> 		; bne 1f / no, then branch
  2804 00004A0C C0E902              <1> 	shr	cl, 2
  2805                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2806                              <1> 		        ; / read/write bits
  2807                              <1> 		; asrb r2
  2808                              <1> access_1: ; 1:
  2809 00004A0F 20D1                <1> 	and	cl, dl
  2810                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2811                              <1> 			     ; / in access call
  2812 00004A11 7513                <1> 	jnz	short access_2
  2813                              <1> 		; bne 1f
  2814 00004A13 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2815                              <1> 		; tstb u.uid
  2816 00004A15 740F                <1> 	jz	short access_2 ; yes, super user
  2817                              <1> 	;jnz	error
  2818                              <1> 		; beq 1f
  2819                              <1> 		; jmp error
  2820 00004A17 C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2820 00004A1F 0000                <1>
  2821                              <1> 			; 'permission denied !' error
  2822 00004A21 E9E1E7FFFF          <1> 	jmp	error
  2823                              <1> 
  2824                              <1> access_2: ; 1:
  2825                              <1> 	; DL = flags
  2826 00004A26 C3                  <1> 	retn
  2827                              <1> 		; rts r0
  2828                              <1> 
  2829                              <1> setimod:
  2830                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2831                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2832                              <1> 	;
  2833                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2834                              <1> 	; the inode has been modified. Also puts the time of modification
  2835                              <1> 	; into the inode.
  2836                              <1> 	;
  2837                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2838                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2839                              <1> 	;
  2840                              <1> 	
  2841                              <1> 	; push 	edx
  2842 00004A27 50                  <1> 	push	eax
  2843                              <1> 
  2844 00004A28 C605[02660000]01    <1> 	mov 	byte [imod], 1
  2845                              <1> 		; movb $1,imod / set current i-node modified bytes
  2846                              <1> 	; Erdogan Tan 14-7-2012
  2847 00004A2F E821E3FFFF          <1> 	call 	epoch
  2848                              <1> 		 ; mov s.time,i.mtim 
  2849                              <1> 			    ; / put present time into file modified time
  2850                              <1> 		 ; mov s.time+2,i.mtim+2
  2851                              <1> 
  2852 00004A34 A3[1E630000]        <1> 	mov 	[i.mtim], eax
  2853                              <1> 	
  2854                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2855                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2856 00004A39 833D[1A630000]00    <1> 	cmp	dword [i.ctim], 0
  2857 00004A40 7505                <1> 	jnz	short setimod_ok
  2858                              <1> 
  2859 00004A42 A3[1A630000]        <1> 	mov 	[i.ctim], eax
  2860                              <1> 
  2861                              <1> setimod_ok: ; 31/07/2013
  2862 00004A47 58                  <1> 	pop	eax
  2863                              <1> 	;pop	edx
  2864                              <1> 	
  2865 00004A48 C3                  <1> 	retn
  2866                              <1> 		; rts r0
  2867                              <1> 
  2868                              <1> itrunc:
  2869                              <1> 	; 03/02/2022
  2870                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2871                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2872                              <1> 	;
  2873                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2874                              <1> 	;  to zero length.
  2875                              <1> 	;
  2876                              <1> 	; INPUTS ->
  2877                              <1> 	;    r1 - i-number of i-node
  2878                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2879                              <1> 	;    i.flgs - large file flag		
  2880                              <1> 	;    i.size - size of file	
  2881                              <1> 	; 	 
  2882                              <1> 	; OUTPUTS ->
  2883                              <1> 	;    i.flgs - large file flag is cleared
  2884                              <1> 	;    i.size - set to 0	
  2885                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2886                              <1> 	;    setimod - set to indicate i-node has been modified
  2887                              <1> 	;    r1 - i-number of i-node  					
  2888                              <1> 	;
  2889                              <1> 	; ((AX = R1)) input/output
  2890                              <1> 	;
  2891                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2892                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2893                              <1> 
  2894 00004A49 E8CFFEFFFF          <1> 	call	iget
  2895                              <1> 		; jsr r0,iget
  2896 00004A4E BE[0A630000]        <1> 	mov	esi, i.dskp
  2897                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2898 00004A53 31C0                <1> 	xor	eax, eax
  2899                              <1> itrunc_1: ; 1:
  2900 00004A55 66AD                <1> 	lodsw
  2901                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2902                              <1> 	; 03/02/2022
  2903 00004A57 09C0                <1> 	or	eax, eax
  2904                              <1> 	;or 	ax, ax
  2905 00004A59 7433                <1> 	jz	short itrunc_5
  2906                              <1> 		; beq 5f
  2907 00004A5B 56                  <1> 	push	esi
  2908                              <1> 		; mov r2,-(sp)
  2909                              <1> 	; 03/02/2022
  2910 00004A5C F605[05630000]10    <1> 	test	byte [i.flgs+1], 10h
  2911                              <1> 	;test	word [i.flgs], 1000h
  2912                              <1> 		; bit $10000,i.flgs / test large file bit?
  2913 00004A63 7423                <1> 	jz	short itrunc_4
  2914                              <1> 		; beq 4f / if clear, branch
  2915 00004A65 50                  <1> 	push	eax
  2916                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2917 00004A66 E86B0A0000          <1> 	call	dskrd
  2918                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2919                              <1> 			     ; / pointed to by r5
  2920                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2921                              <1> 	; 03/02/2022
  2922 00004A6B 31C9                <1> 	xor	ecx, ecx
  2923 00004A6D FEC5                <1> 	inc	ch ; mov ch, 1
  2924                              <1> 	; ecx = 256
  2925                              <1> 	;mov	ecx, 256
  2926                              <1> 		; mov $256.,r3 / move word count into r3
  2927 00004A6F 89DE                <1> 	mov	esi, ebx
  2928                              <1> itrunc_2: ; 2:
  2929 00004A71 66AD                <1> 	lodsw
  2930                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2931                              <1> 			     ; / physical block number
  2932                              <1> 	; 03/02/2022
  2933 00004A73 21C0                <1> 	and	eax, eax
  2934                              <1> 	;and	ax, ax
  2935 00004A75 7407                <1> 	jz	short itrunc_3
  2936                              <1> 		; beq 3f / branch if zero
  2937                              <1> 	; 03/02/2022
  2938 00004A77 51                  <1> 	push	ecx
  2939                              <1> 	;push	cx
  2940                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2941                              <1> 	;push	esi
  2942                              <1> 		; mov r5,-(sp)
  2943 00004A78 E855FEFFFF          <1> 	call	free
  2944                              <1> 		; jsr r0,free / free block in free storage map
  2945                              <1> 	;pop	esi
  2946                              <1> 		; mov(sp)+,r5
  2947                              <1> 	;pop	cx
  2948 00004A7D 59                  <1> 	pop	ecx
  2949                              <1> 		; mov (sp)+,r3
  2950                              <1> itrunc_3: ; 3:
  2951 00004A7E E2F1                <1> 	loop	itrunc_2
  2952                              <1> 		; dec r3 / decrement word count
  2953                              <1> 		; bgt 2b / branch if positive
  2954 00004A80 58                  <1> 	pop	eax
  2955                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2956                              <1> 			     ; / indirect block
  2957                              <1> 	; 01/08/2013
  2958                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2959                              <1> 	; 03/02/2022
  2960 00004A81 8025[05630000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2961                              <1> itrunc_4: ; 4:
  2962 00004A88 E845FEFFFF          <1> 	call	free
  2963                              <1> 		; jsr r0,free / free indirect block
  2964 00004A8D 5E                  <1> 	pop	esi
  2965                              <1> 		; mov (sp)+,r2
  2966                              <1> itrunc_5: ; 5:
  2967 00004A8E 81FE[1A630000]      <1> 	cmp	esi, i.dskp+16
  2968                              <1> 		; cmp r2,$i.dskp+16.
  2969 00004A94 72BF                <1> 	jb	short itrunc_1	
  2970                              <1> 		; bne 1b / branch until all i.dskp entries check
  2971                              <1> 	; 03/02/2022
  2972                              <1> 	;and	byte [i.flgs+1], 0EFh
  2973                              <1> 	; 01/08/2013
  2974                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2975                              <1> 		; bic $10000,i.flgs / clear large file bit
  2976 00004A96 BF[0A630000]        <1> 	mov	edi, i.dskp
  2977                              <1> 	;mov	cx, 8
  2978                              <1> 	;xor 	ax, ax
  2979                              <1> 	; 03/02/2022
  2980 00004A9B 29C9                <1> 	sub	ecx, ecx
  2981 00004A9D B108                <1> 	mov	cl, 8
  2982 00004A9F 29C0                <1> 	sub	eax, eax
  2983 00004AA1 66A3[08630000]      <1> 	mov	[i.size], ax ; 0
  2984                              <1> 		; clr i.size / zero file size
  2985 00004AA7 F366AB              <1> 	rep	stosw
  2986                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2987                              <1> 			   ; / zero block pointers
  2988 00004AAA E878FFFFFF          <1> 	call	setimod
  2989                              <1> 		; jsr r0,setimod / set i-node modified flag
  2990 00004AAF 66A1[F0650000]      <1> 	mov	ax, [ii]
  2991                              <1> 		; mov ii,r1
  2992 00004AB5 C3                  <1> 	retn
  2993                              <1> 		; rts r0
  2994                              <1> 
  2995                              <1> imap:
  2996                              <1> 	; 12/02/2022
  2997                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2998                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2999                              <1> 	;
  3000                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3001                              <1> 	; allocation bit for an i-node whose number in r1.
  3002                              <1> 	;
  3003                              <1> 	; INPUTS ->
  3004                              <1> 	;    r1 - contains an i-number
  3005                              <1> 	;    fsp - start of table containing open files
  3006                              <1> 	;
  3007                              <1> 	; OUTPUTS ->
  3008                              <1> 	;    r2 - byte address of byte with the allocation bit
  3009                              <1> 	;    mq - a mask to locate the bit position.	
  3010                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3011                              <1> 	;
  3012                              <1> 	; ((AX = R1)) input/output
  3013                              <1> 	; ((DL/DX = MQ)) output
  3014                              <1> 	; ((BX = R2)) output
  3015                              <1> 	;
  3016                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3017                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3018                              <1> 	;
  3019                              <1> 		; / get the byte that has the allocation bit for 
  3020                              <1> 		; / the i-number contained in r1
  3021                              <1> 	;mov	dx, 1
  3022 00004AB6 B201                <1> 	mov	dl, 1
  3023                              <1> 		; mov $1,mq / put 1 in the mq
  3024 00004AB8 0FB7D8              <1> 	movzx	ebx, ax
  3025                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3026                              <1>  		          ; / in the map we must find
  3027 00004ABB 6683EB29            <1> 	sub	bx, 41
  3028                              <1> 		; sub $41.,r2 / r2 has i-41
  3029 00004ABF 88D9                <1> 	mov	cl, bl
  3030                              <1> 		; mov r2,r3 / r3 has i-41
  3031 00004AC1 80E107              <1> 	and	cl, 7
  3032                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3033                              <1> 			   ; / the bit position
  3034 00004AC4 7402                <1> 	jz	short imap1
  3035                              <1> 	;shl	dx, cl
  3036 00004AC6 D2E2                <1> 	shl	dl, cl
  3037                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3038                              <1> imap1:			   ; / to the left to mask the correct bit
  3039                              <1> 	; 03/02/2022
  3040 00004AC8 C1EB03              <1> 	shr	ebx, 3
  3041                              <1> 	;shr	bx, 3
  3042                              <1> 		; asr r2
  3043                              <1> 		; asr r2
  3044                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3045                              <1> 		       ; / from the start of the map
  3046                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3047 00004ACB BE[D8760000]        <1> 	mov	esi, systm
  3048                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3049                              <1> 				; / the super block for drum
  3050                              <1> 	;cmp	word [cdev], 0
  3051 00004AD0 803D[F4650000]00    <1> 	cmp	byte [cdev], 0
  3052                              <1> 		; tst cdev / is the device the disk
  3053 00004AD7 7606                <1> 	jna	short imap2
  3054                              <1> 		; beq 1f / yes
  3055 00004AD9 81C608020000        <1> 	add	esi, mount - systm
  3056                              <1> 		; add $mount-systm,r2 / for mounted device,
  3057                              <1> 			; / r2 points to 1st word of its super block
  3058                              <1> imap2: ; 1:
  3059 00004ADF 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3060                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3061 00004AE2 6683C304            <1> 	add	bx, 4
  3062 00004AE6 01F3                <1> 	add	ebx, esi
  3063                              <1>         	; add (sp)+,r2 / ?
  3064                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3065                              <1> 		      ;; (2 + free map size + 2)
  3066                              <1> 		; add $2,r2 / ?
  3067                              <1>  	
  3068                              <1> 	; 12/02/2022
  3069 00004AE8 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3070 00004AEE 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3071                              <1> 			  ; if inode num overs inode count
  3072                              <1> 
  3073                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3074                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3075                              <1> 
  3076                              <1> 	; 11/02/2022
  3077                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3078                              <1> 	;	(number of requested inode > inode count)
  3079                              <1> 
  3080 00004AF0 C3                  <1> 	retn
  3081                              <1> 		; rts r0
  2055                                  %include 'u6.s'        ; 31/05/2015
  2056                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS6.INC
  2057                              <1> ; Last Modification: 14/07/2022
  2058                              <1> ; ----------------------------------------------------------------------------
  2059                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2060                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2061                              <1> ;
  2062                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2063                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2064                              <1> ; <Bell Laboratories (17/3/1972)>
  2065                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2066                              <1> ;
  2067                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2068                              <1> ;
  2069                              <1> ; ****************************************************************************
  2070                              <1> ; 18/11/2015
  2071                              <1> 
  2072                              <1> readi:
  2073                              <1> 	; 03/02/2022
  2074                              <1> 	; 20/05/2015
  2075                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2076                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2077                              <1> 	;
  2078                              <1> 	; Reads from an inode whose number in R1
  2079                              <1> 	; 
  2080                              <1> 	; INPUTS ->
  2081                              <1> 	;    r1 - inode number
  2082                              <1> 	;    u.count - byte count user desires
  2083                              <1> 	;    u.base - points to user buffer
  2084                              <1> 	;    u.fofp - points to word with current file offset
  2085                              <1> 	; OUTPUTS ->
  2086                              <1> 	;    u.count - cleared
  2087                              <1> 	;    u.nread - accumulates total bytes passed back
  2088                              <1> 	;
  2089                              <1> 	; ((AX = R1)) input/output
  2090                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2091                              <1>         ;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -14/07/2022- 
  2092                              <1> 
  2093 00004AF1 31D2                <1> 	xor	edx, edx ; 0
  2094 00004AF3 8915[38660000]      <1> 	mov 	[u.nread], edx ; 0
  2095                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2096 00004AF9 668915[6F660000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2097 00004B00 3915[34660000]      <1> 	cmp 	[u.count], edx ; 0
  2098                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2099 00004B06 7701                <1> 	ja 	short readi_1 ; 1f
  2100                              <1> 		 ; bgt 1f / yes, branch
  2101 00004B08 C3                  <1> 	retn
  2102                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2103                              <1> readi_1: ; 1:
  2104                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2105 00004B09 6683F828            <1> 	cmp	ax, 40
  2106                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2107                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2108                              <1>         ;ja	dskr 
  2109                              <1> 		 ; ble 1f / yes, branch
  2110                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2111                              <1> 		 ;         / read file with i-node number (r1)
  2112                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2113                              <1> 	; 03/02/2022
  2114 00004B0D 7605                <1> 	jna	short readi_3
  2115 00004B0F E9CF000000          <1> 	jmp	dskr
  2116                              <1> readi_3:
  2117                              <1> 	; (20/05/2015)
  2118 00004B14 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2119                              <1> 	; 1:
  2120 00004B15 0FB6D8              <1> 	movzx	ebx, al
  2121                              <1> 	; 03/02/2022
  2122 00004B18 C1E302              <1> 	shl	ebx, 2
  2123                              <1> 	;shl	bx, 2
  2124                              <1> 		 ; asl r1 / multiply inode number by 2
  2125 00004B1B 81C3[1F4B0000]      <1> 	add	ebx, readi_2 - 4
  2126 00004B21 FF23                <1> 	jmp	dword [ebx]	
  2127                              <1> 		 ; jmp *1f-2(r1)
  2128                              <1> readi_2: ; 1:
  2129 00004B23 [6F4B0000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2130                              <1> 		 ;rtty / tty; r1=2
  2131                              <1> 		 ;rppt / ppt; r1=4
  2132 00004B27 [BF4B0000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2133                              <1> 		 ;rmem / mem; r1=6
  2134                              <1> 		 ;rrf0 / rf0
  2135                              <1> 		 ;rrk0 / rk0
  2136                              <1> 		 ;rtap / tap0
  2137                              <1> 		 ;rtap / tap1
  2138                              <1> 		 ;rtap / tap2
  2139                              <1> 		 ;rtap / tap3
  2140                              <1> 		 ;rtap / tap4
  2141                              <1> 		 ;rtap / tap5
  2142                              <1> 		 ;rtap / tap6
  2143                              <1> 		 ;rtap / tap7
  2144 00004B2B [9F530000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2145 00004B2F [9F530000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2146 00004B33 [9F530000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2147 00004B37 [9F530000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2148 00004B3B [9F530000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2149 00004B3F [9F530000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2150 00004B43 [D44B0000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2151 00004B47 [BB4B0000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2152                              <1> 		 ;rcvt / tty0
  2153 00004B4B [BB4B0000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2154                              <1> 		 ;rcvt / tty1
  2155 00004B4F [BB4B0000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2156                              <1> 		 ;rcvt / tty2
  2157 00004B53 [BB4B0000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2158                              <1> 		 ;rcvt / tty3
  2159 00004B57 [BB4B0000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2160                              <1> 		 ;rcvt / tty4
  2161 00004B5B [BB4B0000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2162                              <1> 		 ;rcvt / tty5
  2163 00004B5F [BB4B0000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2164                              <1> 		 ;rcvt / tty6
  2165 00004B63 [BB4B0000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2166                              <1> 		 ;rcvt / tty7
  2167 00004B67 [BB4B0000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2168                              <1> 		 ;rcrd / crd
  2169 00004B6B [BB4B0000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2170                              <1> 
  2171                              <1> rtty: ; / read from console tty
  2172                              <1> 	; 03/02/2022
  2173                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2174                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2175                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2176                              <1> 	;	     must be written immediate on video page (screen)
  2177                              <1> 	;	     when it is required.	
  2178                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2179                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2180                              <1> 	;
  2181                              <1> 	; Console tty buffer is PC keyboard buffer
  2182                              <1> 	; and keyboard-keystroke handling is different than original
  2183                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2184                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2185                              <1> 	;
  2186                              <1> 	; 06/12/2013
  2187 00004B6F 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2188 00004B76 8A83[63630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2189                              <1> rttys:
  2190                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2191                              <1> 	               ; / of the control and status block
  2192                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2193                              <1> 		       ; / tty buffer
  2194                              <1> 	; 28/07/2013
  2195 00004B7C A2[5E660000]        <1> 	mov 	[u.ttyn], al
  2196                              <1> 	; 13/01/2014
  2197 00004B81 FEC0                <1> 	inc	al
  2198 00004B83 A2[40660000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2199                              <1> rtty_nc: ; 01/02/2014
  2200                              <1> 	; 29/09/2013
  2201                              <1> 	;mov	ecx, 10
  2202                              <1> 	; 03/02/2022
  2203 00004B88 29C9                <1> 	sub	ecx, ecx
  2204 00004B8A B10A                <1> 	mov	cl, 10
  2205                              <1> rtty_1: 	; 01/02/2014
  2206                              <1> 	;push 	cx ; 29/09/2013
  2207                              <1> 	; 03/02/2022
  2208 00004B8C 51                  <1> 	push	ecx
  2209                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2210 00004B8D B001                <1> 	mov 	al, 1
  2211 00004B8F E80E0B0000          <1> 	call 	getc
  2212                              <1> 	; 03/02/2022
  2213 00004B94 59                  <1> 	pop	ecx
  2214                              <1> 	;pop 	cx ; 29/09/2013	
  2215 00004B95 7516                <1> 	jnz	short rtty_2
  2216                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2217                              <1> 	               ; / of chars. Is this number non-zero?
  2218 00004B97 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2219                              <1> 	; 05/10/2013
  2220 00004B99 8A25[5E660000]      <1> 	mov	ah, [u.ttyn]
  2221                              <1> 	; 29/09/2013
  2222 00004B9F E898FBFFFF          <1> 	call	sleep
  2223                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2224                              <1>                 ;           / (120 chars.)
  2225                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2226 00004BA4 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2227                              <1> 
  2228                              <1> rtty_idle:
  2229                              <1> 	; 29/07/2013
  2230 00004BA6 E804FBFFFF          <1> 	call 	idle
  2231 00004BAB EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2232                              <1> 	;1:
  2233                              <1> 		; tst 2(r5) / is the number of characters zero
  2234                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2235                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2236                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2237                              <1> 		          ; / contains the next char.
  2238                              <1> 		; dec 2(r5) / decrement the character count
  2239                              <1> rtty_2:
  2240 00004BAD 30C0                <1> 	xor 	al, al
  2241 00004BAF E8EE0A0000          <1> 	call 	getc
  2242 00004BB4 E892000000          <1> 	call	passc
  2243                              <1> 		; jsr r0,passc / move the character to core (user)
  2244                              <1> 	;; 17/10/2015 - 16/07/2015
  2245                              <1> 	; 19/06/2014
  2246                              <1> 	;;jnz	short rtty_nc
  2247 00004BB9 58                  <1> 	pop	eax  ; (20/05/2015)
  2248 00004BBA C3                  <1> 	retn 
  2249                              <1> ;ret1:
  2250                              <1> 		; jmp ret / return to caller via 'ret'
  2251                              <1> 
  2252                              <1> rcvt:   ; < receive/read character from tty >
  2253                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2254                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2255                              <1> 	;
  2256                              <1> 	; Retro UNIX 8086 v1 modification !
  2257                              <1> 	; 
  2258                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2259                              <1> 	;		(exactly different than this one)
  2260                              <1> 	;	was in 'u9.s' file.
  2261                              <1> 	;
  2262 00004BBB 2C0A                <1> 	sub 	al, 10
  2263                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2264                              <1> 	; 16/07/2013
  2265                              <1> 	; 21/05/2013
  2266 00004BBD EBBD                <1>         jmp     short rttys
  2267                              <1>       
  2268                              <1> ;rppt: / read paper tape
  2269                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2270                              <1> ;			 / places
  2271                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2272                              <1> ;		       / also enables read bit in prs
  2273                              <1> ;	jsr	r0,passc / place character in users buffer area
  2274                              <1> ;	br	rppt
  2275                              <1> 
  2276                              <1> rmem: ; / transfer characters from memory to a user area of core
  2277                              <1> 	; 17/10/2015
  2278                              <1> 	; 11/06/2015
  2279                              <1> 	; 24/05/2015
  2280                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2281                              <1> 	;
  2282 00004BBF 8B35[20660000]      <1> 	mov     esi, [u.fofp]
  2283                              <1> rmem_1:
  2284 00004BC5 8B1E                <1>         mov     ebx, [esi]        
  2285                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2286                              <1> 		               ; / to be transferred to user
  2287 00004BC7 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2288                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2289                              <1> 			    ; / char in memory file
  2290 00004BC9 8A03                <1> 	mov	al, [ebx]
  2291                              <1> 		; movb (r1),r1 / get character from memory file, 
  2292                              <1> 		             ; / put it in r1
  2293 00004BCB E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2294                              <1> 			     ;  / the next byte of the users core area
  2295                              <1> 		; br rmem / continue
  2296 00004BD0 75F3                <1> 	jnz	short rmem_1
  2297                              <1> ret_:
  2298 00004BD2 58                  <1> 	pop	eax ; 09/06/2015
  2299 00004BD3 C3                  <1> 	retn
  2300                              <1> 
  2301                              <1> rlpr:
  2302                              <1> ;1:
  2303                              <1> ;rcrd:
  2304 00004BD4 C705[5F660000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2304 00004BDC 0000                <1>
  2305 00004BDE E924E6FFFF          <1> 	jmp	error
  2306                              <1> 		;jmp	error / see 'error' routine
  2307                              <1> 
  2308                              <1> dskr:
  2309                              <1> 	; 12/10/2015
  2310                              <1> 	; 21/08/2015
  2311                              <1> 	; 25/07/2015
  2312                              <1> 	; 10/07/2015
  2313                              <1> 	; 16/06/2015
  2314                              <1> 	; 31/05/2015
  2315                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2316                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2317                              <1> dskr_0:
  2318 00004BE3 50                  <1> 	push	eax
  2319                              <1> 		; mov (sp),r1 / i-number in r1
  2320                              <1> 	; AX = i-number
  2321 00004BE4 E834FDFFFF          <1> 	call	iget
  2322                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2323 00004BE9 0FB715[08630000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2324                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2325 00004BF0 8B1D[20660000]      <1> 	mov	ebx, [u.fofp]
  2326 00004BF6 2B13                <1> 	sub	edx, [ebx]
  2327                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2328                              <1>         ; 12/10/2015
  2329                              <1> 	; jna     short ret_ 
  2330                              <1> 		; blos ret
  2331 00004BF8 7709                <1> 	ja	short dskr_1
  2332                              <1> 	;
  2333                              <1> dskr_retn: ; 12/10/2015
  2334 00004BFA 58                  <1> 	pop	eax
  2335 00004BFB C605[71660000]00    <1> 	mov	byte [u.kcall], 0
  2336 00004C02 C3                  <1> 	retn	
  2337                              <1> dskr_1: 
  2338 00004C03 3B15[34660000]      <1> 	cmp     edx, [u.count] 
  2339                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2340                              <1> 			       ; / to carry out read
  2341 00004C09 7306                <1> 	jnb	short dskr_2
  2342                              <1> 		; bhis 1f
  2343 00004C0B 8915[34660000]      <1> 	mov	[u.count], edx
  2344                              <1> 		; mov r2,u.count / no, just read to end of file
  2345                              <1> dskr_2: ; 1:
  2346                              <1> 	; AX = i-number
  2347 00004C11 E89EFBFFFF          <1> 	call	mget
  2348                              <1> 		; jsr r0,mget / returns physical block number of block 
  2349                              <1> 			    ; / in file where offset points
  2350                              <1> 	; EAX = physical block number
  2351 00004C16 E8BB080000          <1> 	call	dskrd
  2352                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2353                              <1> 			     ; / 1st word of data in buffer
  2354                              <1> 	; 09/06/2015
  2355 00004C1B 803D[71660000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2356 00004C22 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2357 00004C24 66833D[6F660000]00  <1> 	cmp	word [u.pcount], 0
  2358 00004C2C 7705                <1> 	ja	short dskr_4
  2359                              <1> dskr_3:
  2360                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2361 00004C2E E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2362                              <1> dskr_4:
  2363                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2364 00004C33 E831030000          <1> 	call	sioreg
  2365                              <1> 		; jsr r0,sioreg
  2366 00004C38 87F7                <1> 	xchg	esi, edi
  2367                              <1> 	; EDI = file (user data) offset
  2368                              <1> 	; ESI = sector (I/O) buffer offset
  2369                              <1> 	; ECX = byte count
  2370 00004C3A F3A4                <1> 	rep	movsb
  2371                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2372                              <1> 		                 ; / starting at u.base
  2373                              <1> 		; dec r3
  2374                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2375                              <1> 	; 25/07/2015
  2376                              <1> 	; eax = remain bytes in buffer
  2377                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2378 00004C3C 09C0                <1> 	or	eax, eax
  2379 00004C3E 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2380                              <1> 	; 03/08/2013
  2381                              <1> 	;pop	eax
  2382 00004C40 390D[34660000]      <1> 	cmp	[u.count], ecx ; 0
  2383                              <1> 		; tst u.count / all bytes read off disk
  2384                              <1> 		; bne dskr
  2385                              <1> 		; br ret
  2386                              <1>         ;ja      short dskr_0
  2387                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2388                              <1> 	;retn
  2389                              <1> 	; 12/10/2015
  2390 00004C46 76B2                <1> 	jna	short dskr_retn
  2391 00004C48 58                  <1> 	pop	eax  ; (i-node number)
  2392 00004C49 EB98                <1> 	jmp	short dskr_0
  2393                              <1> 	
  2394                              <1> passc:
  2395                              <1> 	; 18/10/2015
  2396                              <1> 	; 10/07/2015
  2397                              <1> 	; 01/07/2015
  2398                              <1> 	; 08/06/2015
  2399                              <1> 	; 04/06/2015
  2400                              <1> 	; 20/05/2015
  2401                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2402                              <1> 	;
  2403                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2404                              <1> 	;		      to physical address
  2405 00004C4B 66833D[6F660000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2406                              <1> 			     ; 1-4095 --> use previous physical base address
  2407                              <1> 			     ; in [u.pbase]
  2408 00004C53 7705                <1> 	ja	short passc_3
  2409                              <1> 	; 08/06/2015 - 10/07/2015
  2410 00004C55 E82C000000          <1> 	call	trans_addr_w
  2411                              <1> passc_3:
  2412                              <1> 	; 19/05/2015
  2413 00004C5A 66FF0D[6F660000]    <1> 	dec	word [u.pcount]
  2414                              <1> 	;
  2415 00004C61 8B1D[6B660000]      <1> 	mov	ebx, [u.pbase]
  2416 00004C67 8803                <1> 	mov	[ebx], al
  2417                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2418                              <1> 		               ; / users buffer
  2419 00004C69 FF05[30660000]      <1> 	inc	dword [u.base]
  2420                              <1> 		; inc u.base / increment the pointer to point to 
  2421                              <1> 			  ; / the next byte in users buffer
  2422 00004C6F FF05[6B660000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2423 00004C75 FF05[38660000]      <1> 	inc	dword [u.nread]
  2424                              <1> 		; inc u.nread / increment the number of bytes read
  2425 00004C7B FF0D[34660000]      <1> 	dec	dword [u.count]
  2426                              <1> 		; dec u.count / decrement the number of bytes to be read
  2427                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2428 00004C81 C3                  <1> 	retn
  2429                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2430                              <1> 		             ; / 'readi' by:
  2431                              <1> 		;/ (1) pop the return address off the stack into r0
  2432                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2433                              <1> 	;1:
  2434                              <1> 		; clr	*$ps / clear processor status
  2435                              <1> 		; rts r0 / return to address currently on top of stack
  2436                              <1> 
  2437                              <1> trans_addr_r:
  2438                              <1> 	; Translate virtual address to physical address 
  2439                              <1> 	; for reading from user's memory space
  2440                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2441                              <1> 	; 18/10/2015
  2442                              <1> 	; 10/07/2015
  2443                              <1> 	; 09/06/2015
  2444                              <1> 	; 08/06/2015 
  2445                              <1> 	; 04/06/2015
  2446                              <1> 	;
  2447                              <1> 	; 18/10/2015
  2448 00004C82 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2449 00004C84 EB04                <1> 	jmp 	short trans_addr_rw
  2450                              <1> 
  2451                              <1> 	;push	eax
  2452                              <1> 	;push	ebx
  2453                              <1> 	;mov	ebx, [u.base]
  2454                              <1> 	;call	get_physical_addr ; get physical address
  2455                              <1> 	;;jnc	short cpass_0
  2456                              <1> 	;jnc	short passc_1
  2457                              <1> 	;mov	[u.error], eax
  2458                              <1> 	;;pop	ebx
  2459                              <1> 	;;pop	eax
  2460                              <1> 	;jmp	error
  2461                              <1> ;cpass_0:
  2462                              <1> 	; 18/10/2015
  2463                              <1> 	; 20/05/2015
  2464                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2465                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2466                              <1> 	;pop	ebx
  2467                              <1> 	;pop	eax
  2468                              <1> 	;retn	; 08/06/2015
  2469                              <1> 
  2470                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2471                              <1> trans_addr_w:
  2472                              <1> 	; Translate virtual address to physical address 
  2473                              <1> 	; for writing to user's memory space
  2474                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2475                              <1> 	; 18/10/2015
  2476                              <1> 	; 29/07/2015
  2477                              <1> 	; 10/07/2015
  2478                              <1> 	; 09/06/2015
  2479                              <1> 	; 08/06/2015
  2480                              <1> 	; 04/06/2015 (passc)
  2481                              <1> 	;
  2482                              <1> 	; 18/10/2015
  2483 00004C86 29D2                <1> 	sub	edx, edx
  2484 00004C88 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2485                              <1> trans_addr_rw:
  2486 00004C8A 50                  <1> 	push	eax
  2487 00004C8B 53                  <1> 	push	ebx
  2488                              <1> 	; 18/10/2015
  2489 00004C8C 52                  <1> 	push 	edx ; r/w sign (in DL)
  2490                              <1> 	;
  2491 00004C8D 8B1D[30660000]      <1> 	mov	ebx, [u.base]
  2492 00004C93 E854DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2493 00004C98 730A                <1> 	jnc	short passc_0
  2494 00004C9A A3[5F660000]        <1> 	mov	[u.error], eax
  2495                              <1> 	;pop	edx
  2496                              <1> 	;pop 	ebx
  2497                              <1> 	;pop	eax
  2498 00004C9F E963E5FFFF          <1> 	jmp	error
  2499                              <1> passc_0:
  2500 00004CA4 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2501 00004CA7 5A                  <1> 	pop	edx ; 18/10/2015
  2502 00004CA8 7517                <1> 	jnz	short passc_1
  2503                              <1> 	; 18/10/2015
  2504 00004CAA 20D2                <1> 	and 	dl, dl
  2505 00004CAC 7413                <1> 	jz	short passc_1
  2506                              <1> 	; 20/05/2015
  2507                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2508                              <1> 	; EBX = linear address
  2509 00004CAE 51                  <1> 	push 	ecx
  2510 00004CAF 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2511 00004CB0 E8A6DBFFFF          <1> 	call 	copy_page
  2512 00004CB5 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2513 00004CB6 59                  <1> 	pop	ecx
  2514 00004CB7 7217                <1> 	jc	short passc_2
  2515                              <1> 	; 03/02/2022
  2516                              <1> 	;push	eax ; physical address of the new/allocated page
  2517                              <1> 	;call	add_to_swap_queue
  2518                              <1> 	;pop	eax
  2519                              <1> 	; 18/10/2015
  2520 00004CB9 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2521                              <1> 	;mov 	ecx, PAGE_SIZE
  2522                              <1> 	;sub	ecx, ebx 
  2523 00004CBF 01D8                <1> 	add	eax, ebx  
  2524                              <1> passc_1: 
  2525                              <1> 	; 18/10/2015
  2526                              <1> 	; 20/05/2015
  2527 00004CC1 A3[6B660000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2528 00004CC6 66890D[6F660000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2529 00004CCD 5B                  <1> 	pop	ebx
  2530 00004CCE 58                  <1> 	pop	eax
  2531 00004CCF C3                  <1> 	retn	; 08/06/2015
  2532                              <1> passc_2:
  2533 00004CD0 C705[5F660000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2533 00004CD8 0000                <1>
  2534                              <1> 	;pop 	ebx
  2535                              <1> 	;pop	eax
  2536 00004CDA E928E5FFFF          <1> 	jmp	error
  2537                              <1> 
  2538                              <1> writei:
  2539                              <1> 	; 13/06/2022
  2540                              <1> 	; 03/02/2022
  2541                              <1> 	; 20/05/2015
  2542                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2543                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2544                              <1> 	;
  2545                              <1> 	; Write data to file with inode number in R1
  2546                              <1> 	; 
  2547                              <1> 	; INPUTS ->
  2548                              <1> 	;    r1 - inode number
  2549                              <1> 	;    u.count - byte count to be written
  2550                              <1> 	;    u.base - points to user buffer
  2551                              <1> 	;    u.fofp - points to word with current file offset
  2552                              <1> 	; OUTPUTS ->
  2553                              <1> 	;    u.count - cleared
  2554                              <1> 	;    u.nread - accumulates total bytes passed back	
  2555                              <1> 	; ((AX = R1))
  2556                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2557                              <1> 	;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -14/07/2022-	
  2558                              <1> 
  2559 00004CDF 31C9                <1> 	xor	ecx, ecx
  2560 00004CE1 890D[38660000]      <1> 	mov 	[u.nread], ecx  ; 0
  2561                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2562                              <1> 		            ; / read or write calls
  2563 00004CE7 66890D[6F660000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2564 00004CEE 390D[34660000]      <1> 	cmp 	[u.count], ecx
  2565                              <1> 	;	; tst u.count / test the byte count specified by the user
  2566 00004CF4 770B                <1> 	ja 	short writei_1 ; 1f
  2567                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2568                              <1> 
  2569                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2570 00004CF6 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2571 00004CF9 7505                <1> 	jne	short writei_0
  2572 00004CFB E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2573                              <1> writei_0:
  2574 00004D00 C3                  <1> 	retn
  2575                              <1> 	;	; rts r0 / no, return - no writing to do
  2576                              <1> writei_1: ;1:
  2577                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2578 00004D01 6683F828            <1> 	cmp 	ax, 40
  2579                              <1> 		; cmp r1,$40.
  2580                              <1> 		; / does the i-node number indicate a special file?
  2581                              <1> 	;ja	dskw 
  2582                              <1> 		; bgt dskw / no, branch to standard file output
  2583                              <1> 	; 03/02/2022
  2584 00004D05 7605                <1> 	jna	short writei_3
  2585 00004D07 E958010000          <1> 	jmp	dskw
  2586                              <1> writei_3:
  2587                              <1> 	; (20/05/2015)
  2588 00004D0C 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2589 00004D0D 0FB6D8              <1> 	movzx	ebx, al
  2590                              <1> 	; 03/02/2022
  2591 00004D10 C1E302              <1> 	shl	ebx, 2
  2592                              <1> 	;shl	bx, 2
  2593                              <1> 		; asl r1 / yes, calculate the index into the special file
  2594 00004D13 81C3[174D0000]      <1> 	add	ebx, writei_2 - 4
  2595 00004D19 FF23                <1> 	jmp	dword [ebx]	
  2596                              <1> 		; jmp *1f-2(r1)
  2597                              <1> 		; / jump table and jump to the appropriate routine
  2598                              <1> writei_2: ;1:
  2599 00004D1B [674D0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2600                              <1> 		 ;wtty / tty; r1=2
  2601                              <1> 		 ;wppt / ppt; r1=4
  2602 00004D1F [BA4D0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2603                              <1> 		 ;wmem / mem; r1=6
  2604                              <1> 		 ;wrf0 / rf0
  2605                              <1> 		 ;wrk0 / rk0
  2606                              <1> 		 ;wtap / tap0
  2607                              <1> 		 ;wtap / tap1
  2608                              <1> 		 ;wtap / tap2
  2609                              <1> 		 ;wtap / tap3
  2610                              <1> 		 ;wtap / tap4
  2611                              <1> 		 ;wtap / tap5
  2612                              <1> 		 ;wtap / tap6
  2613                              <1> 		 ;wtap / tap7
  2614 00004D23 [10540000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2615 00004D27 [10540000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2616 00004D2B [10540000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2617 00004D2F [10540000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2618 00004D33 [10540000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2619 00004D37 [10540000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2620 00004D3B [EA4D0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2621 00004D3F [B44D0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2622                              <1> 		 ;xmtt / tty0
  2623 00004D43 [B44D0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2624                              <1> 		 ;xmtt / tty1
  2625 00004D47 [B44D0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2626                              <1> 		 ;xmtt / tty2
  2627 00004D4B [B44D0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2628                              <1> 		 ;xmtt / tty3
  2629 00004D4F [B44D0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2630                              <1> 		 ;xmtt / tty4
  2631 00004D53 [B44D0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2632                              <1> 		 ;xmtt / tty5
  2633 00004D57 [B44D0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2634                              <1> 		 ;xmtt / tty6
  2635 00004D5B [B44D0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2636                              <1> 		 ;xmtt / tty7
  2637 00004D5F [B44D0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2638                              <1> 		; / wlpr / lpr
  2639 00004D63 [B44D0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2640                              <1> 
  2641                              <1> wtty: ; write to console tty (write to screen)
  2642                              <1> 	; 03/02/2022
  2643                              <1> 	; 18/11/2015
  2644                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2645                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2646                              <1> 	;
  2647                              <1> 	; Console tty output is on current video page
  2648                              <1> 	; Console tty character output procedure is changed here
  2649                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2650                              <1> 	;
  2651 00004D67 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2652 00004D6E 8AA3[63630000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2653 00004D74 88E0                <1> 	mov	al, ah ; 07/07/2014
  2654                              <1> wttys:	
  2655                              <1> 	; 10/10/2013
  2656 00004D76 8825[5E660000]      <1> 	mov 	[u.ttyn], ah
  2657                              <1> 	; 13/01/2014
  2658 00004D7C FEC0                <1> 	inc	al
  2659 00004D7E A2[41660000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2660                              <1> wtty_nc: ; 15/05/2013
  2661                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2662 00004D83 E881010000          <1> 	call	cpass
  2663                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2664                              <1> 		             ; / none go to return address in syswrite
  2665                              <1> 		; tst r1 / is character = null
  2666                              <1> 		; beq wtty / yes, get next character
  2667                              <1> 	; 10/10/2013
  2668 00004D88 7428                <1> 	jz	short wret
  2669                              <1> 	;1 :
  2670                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2671                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2672                              <1> 		;	          / than 20
  2673                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2674                              <1> 	; 27/06/2014
  2675                              <1> wtty_1:
  2676                              <1> 	; AH = tty number
  2677                              <1> 	; AL = ASCII code of the character
  2678                              <1> 	; 15/04/2014
  2679                              <1> 	;push	ax
  2680                              <1> 	; 03/02/2022
  2681 00004D8A 50                  <1> 	push	eax
  2682 00004D8B E880090000          <1> 	call	putc ; 14/05/2013
  2683 00004D90 731D                <1> 	jnc	short wtty_2
  2684                              <1> 	; 18/11/2015
  2685 00004D92 E818F9FFFF          <1> 	call	idle
  2686                              <1> 	;mov	ax, [esp]
  2687                              <1> 	; 03/02/2022
  2688 00004D97 8B0424              <1> 	mov	eax, [esp]
  2689 00004D9A E871090000          <1> 	call	putc
  2690 00004D9F 730E                <1> 	jnc	short wtty_2 
  2691                              <1> 	; 02/06/2014
  2692 00004DA1 8A25[5E660000]      <1> 	mov	ah, [u.ttyn]
  2693 00004DA7 E890F9FFFF          <1> 	call	sleep
  2694                              <1> 	; 03/02/2022
  2695 00004DAC 58                  <1> 	pop	eax
  2696                              <1> 	;pop	ax
  2697 00004DAD EBDB                <1> 	jmp 	short wtty_1
  2698                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2699                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2700                              <1> 			      ; / console tty and
  2701                              <1> 		; br 	2f / place character in list; if none available
  2702                              <1> 		   	  ; / branch to put process to sleep
  2703                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2704                              <1> wtty_2:
  2705                              <1> 	; 15/04/2014
  2706                              <1> 	;pop	ax
  2707                              <1> 	; 03/02/2022
  2708 00004DAF 58                  <1> 	pop	eax
  2709 00004DB0 EBD1                <1> 	jmp	short wtty_nc
  2710                              <1> 		; br wtty
  2711                              <1> wret:	; 10/10/2013 (20/05/2015)
  2712 00004DB2 58                  <1> 	pop	eax
  2713 00004DB3 C3                  <1> 	retn
  2714                              <1> 	;2:
  2715                              <1> 		;mov	r1,-(sp) / place character on stack
  2716                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2717                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2718                              <1> 		;br	1b / try again to place character in clist and output
  2719                              <1> 
  2720                              <1> xmtt:   ; < send/write character to tty >
  2721                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2722                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2723                              <1> 	;
  2724                              <1> 	; Retro UNIX 8086 v1 modification !
  2725                              <1> 	; 
  2726                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2727                              <1> 	;		(exactly different than this one)
  2728                              <1> 	;	was in 'u9.s' file.
  2729                              <1> 	;
  2730 00004DB4 2C0A                <1> 	sub 	al, 10
  2731                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2732                              <1> 	; 10/10/2013
  2733 00004DB6 88C4                <1> 	mov	ah, al
  2734                              <1> 	; 28/07/2013
  2735 00004DB8 EBBC                <1> 	jmp	short wttys
  2736                              <1> 
  2737                              <1> ;wppt:
  2738                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2739                              <1> ;		         / if none return to writei's calling routine
  2740                              <1> ;	jsr	r0,pptoc / output character on ppt
  2741                              <1> ;	br	wppt
  2742                              <1> 
  2743                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2744                              <1> 	; 17/10/2015
  2745                              <1> 	; 11/06/2015
  2746                              <1> 	; 24/05/2015
  2747                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2748                              <1> 	;
  2749 00004DBA 813D[0A070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2749 00004DC0 [D2460000]          <1>
  2750 00004DC4 7415                <1>         je      short wmem_acc_err
  2751                              <1> 	;
  2752 00004DC6 8B35[20660000]      <1>         mov     esi, [u.fofp] 
  2753                              <1> wmem_1:
  2754 00004DCC E838010000          <1> 	call	cpass
  2755                              <1> 		; jsr r0,cpass / get next character from users area of
  2756                              <1> 			     ; / core and put it in r1
  2757                              <1>         	; mov r1,-(sp) / put character on the stack
  2758                              <1> 	; 20/09/2013
  2759 00004DD1 74DF                <1> 	jz	short wret ; wmem_2  
  2760 00004DD3 8B1E                <1>         mov     ebx, [esi]
  2761                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2762 00004DD5 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2763                              <1> 		; inc *u.fofp / increment file offset to point to next
  2764                              <1> 			    ; / available location in file
  2765 00004DD7 8803                <1> 	mov	[ebx], al	
  2766                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2767                              <1> 			        ; / assigned to it
  2768 00004DD9 EBF1                <1> 	jmp	short wmem_1
  2769                              <1> 		; br wmem / continue
  2770                              <1> 	;1:
  2771                              <1> 	;jmp	error / ?
  2772                              <1> ;wmem_2:	
  2773                              <1> ;	; 20/09/2013
  2774                              <1> ;	pop	ax
  2775                              <1> ;	retn
  2776                              <1> 
  2777                              <1> wmem_acc_err:
  2778 00004DDB C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2778 00004DE3 0000                <1>
  2779 00004DE5 E91DE4FFFF          <1> 	jmp	error
  2780                              <1> 
  2781                              <1> ;wlpr:
  2782                              <1> 	; 13/06/2022
  2783                              <1>         ;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2784                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2785                              <1> 		;/	jsr	r0,cpass
  2786                              <1> 		;/	cmp	r0,$'a
  2787                              <1> 		;/	blo	1f
  2788                              <1> 		;/	cmp	r1,$'z
  2789                              <1> 		;/	bhi	1f
  2790                              <1> 		;/	sub	$40,r1
  2791                              <1> 		;/1:
  2792                              <1> 		;/	jsr	r0,lptoc
  2793                              <1> 		;/	br	wlpr
  2794                              <1> 		; br rmem / continue
  2795                              <1> 
  2796                              <1> ; 13/06/2022 - Retro UNIX 386 v1 - PRINTER BIOS (Functions)
  2797                              <1> 
  2798                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2799                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2800                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2801                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2802                              <1> 
  2803                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2804                              <1> 
  2805                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2806                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2807                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2808                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2809                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2810                              <1> RESERVED	equ 00000110b	; NOPS
  2811                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2812                              <1> 
  2813                              <1> ;----------------------------------------------------------------
  2814                              <1> ;								:
  2815                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2816                              <1> ;								:
  2817                              <1> ;   CX has count of bytes to be printed 			:
  2818                              <1> ;   ES:DI point to source buffer contains characters		:
  2819                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2820                              <1> ;								:
  2821                              <1> ;----------------------------------------------------------------
  2822                              <1> 
  2823                              <1> wlpr:
  2824                              <1> 	; 14/07/2022
  2825                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2826                              <1> PRN$WRIT:
  2827                              <1> 	; INPUT:
  2828                              <1> 	;	[u.count] = count of characters to be printed
  2829                              <1> 	;	[u.base] = buffer address in user's memory space
  2830                              <1> 	;
  2831                              <1> 	;	(if ECX = 0, printer status will be returned)
  2832                              <1> 	
  2833                              <1> 	;xor	ebx, ebx
  2834                              <1> PRN$LOOP:
  2835 00004DEA E81A010000          <1> 	call	cpass		  ; Get a character into AL
  2836 00004DEF 7431                <1> 	jz	short pr_exit
  2837                              <1> 	;
  2838 00004DF1 B302                <1> 	mov	bl, 2  ; retry count
  2839                              <1> PRN$OUT:
  2840                              <1> 	; al = character which will be printed
  2841 00004DF3 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2842 00004DF5 E850000000          <1> 	call	PRNOP
  2843 00004DFA 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2844                              <1> PrRetry:
  2845                              <1> 	; al = character
  2846 00004DFC FECB                <1> 	dec	bl
  2847 00004DFE 75F3                <1> 	jnz	short PRN$OUT
  2848                              <1> pr_err_exit:
  2849 00004E00 0FB6C0              <1> 	movzx	eax, al
  2850 00004E03 A3[5F660000]        <1> 	mov	[u.error], eax
  2851 00004E08 A3[10660000]        <1> 	mov	[u.r0], eax ; error code in AL
  2852                              <1> 	;mov 	ebp, [u.sp]
  2853 00004E0D 8B1D[08660000]      <1> 	mov	ebx, [u.sp] ; 14/07/2022
  2854                              <1> 			; Kernel stack at the beginning of sys call
  2855 00004E13 8B15[38660000]      <1> 	mov	edx, [u.nread]
  2856 00004E19 4A                  <1> 	dec	edx ; last char failed
  2857                              <1> 	;mov	[ebp+20], edx ; count of printed characters in edx
  2858 00004E1A 895314              <1> 	mov	[ebx+20], edx ; 14/07/2022
  2859 00004E1D E9E5E3FFFF          <1> 	jmp	error
  2860                              <1> pr_exit:
  2861 00004E22 58                  <1> 	pop	eax ; inode number
  2862                              <1> 
  2863                              <1> 	;mov	eax, [u.nread]
  2864                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2865                              <1> 	;jmp	sysret
  2866 00004E23 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2867                              <1> 
  2868                              <1> ; 13/06/2022
  2869                              <1> 
  2870                              <1> ;----------------------------------------------------------------
  2871                              <1> ;								:
  2872                              <1> ;		PRINTER STATUS ROUTINE				:
  2873                              <1> ;								:
  2874                              <1> ;----------------------------------------------------------------
  2875                              <1> ;
  2876                              <1> 
  2877                              <1> lpr_stat:
  2878                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2879                              <1> PRN$STAT:
  2880 00004E24 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2881 00004E29 750E                <1> 	jnz	short prn_stat_retn
  2882                              <1> 				  ; if error jump to error routine
  2883                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2884 00004E2B B01F                <1> 	mov	al, ERR_PRN_PAPER
  2885 00004E2D F6C420              <1> 	test	ah, NOPAPERSTATUS
  2886 00004E30 7507                <1> 	jnz	short prn_stat_retn
  2887 00004E32 F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2888 00004E35 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2889 00004E37 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2890                              <1> prn_stat_retn:
  2891                              <1> 	; al = error code
  2892                              <1> 	; ah = status flags
  2893 00004E39 A3[10660000]        <1> 	mov	[u.r0], eax
  2894                              <1> 	;movzx	eax, al
  2895                              <1> 	;mov 	[u.error], eax
  2896 00004E3E 58                  <1> 	pop	eax ; discard return address to syswrite
  2897 00004E3F E9E3E3FFFF          <1> 	jmp	sysret
  2898                              <1> prn_stat_ok:
  2899 00004E44 30C0                <1> 	xor	al, al ; 0
  2900 00004E46 EBF1                <1> 	jmp	short prn_stat_retn
  2901                              <1> 
  2902                              <1> ;
  2903                              <1> ;   PRNSTAT	get printer status
  2904                              <1> ;   PRNOP	print a character
  2905                              <1> ;
  2906                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2907                              <1> ; printer routines.  The routines share code which calls on the bios and
  2908                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2909                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2910                              <1> ;
  2911                              <1> ;   INPUT	if PRNOP then character in AL
  2912                              <1> ;
  2913                              <1> ;   OUTPUT	- AL holds error code
  2914                              <1> ;		- AH status byte from printer
  2915                              <1> ;		- flag NZ if error
  2916                              <1> 
  2917                              <1> PRNSTAT:
  2918 00004E48 B402                <1> 	mov	ah, 2		  ; set command for get status 
  2919                              <1> 
  2920                              <1> PRNOP:
  2921                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2922                              <1> 	;
  2923                              <1> 	; Print character (on paper)
  2924                              <1> 
  2925                              <1> 	; INPUT:
  2926                              <1> 	;	al = character to be printed
  2927                              <1> 	; OUTPUT:
  2928                              <1> 	;	zf = 1 -> ok
  2929                              <1> 	;	zf = 0 -> error code in AL
  2930                              <1> 
  2931 00004E4A E8FA0A0000          <1> 	call	int17h	 ; call lpt bios
  2932                              <1> 	
  2933 00004E4F F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  2934 00004E52 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  2935                              <1> 
  2936                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  2937                              <1> 	; THE CONVERSE IS NOT TRUE.
  2938                              <1> 
  2939                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  2940 00004E54 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2941 00004E56 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  2942 00004E59 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  2943                              <1> 	;mov	al, ERR_PRN_IO
  2944 00004E5B FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  2945                              <1> PRNOP1: 
  2946                              <1> 
  2947                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  2948                              <1> 
  2949 00004E5D C3                  <1> 	retn			  ; RETURN WITH ERROR
  2950                              <1>  
  2951                              <1> ; THE BITS SAID NO ERROR.
  2952                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  2953                              <1> 
  2954                              <1> prnop_chk_nrdy:
  2955                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  2956 00004E5E B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  2957                              <1> 	
  2958 00004E60 F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  2959                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  2960                              <1> PRNOP2: 
  2961 00004E63 C3                  <1> 	retn
  2962                              <1> 
  2963                              <1> 
  2964                              <1> dskw: ; / write routine for non-special files
  2965                              <1> 	;
  2966                              <1> 	; 03/02/2022
  2967                              <1> 	; 25/07/2015
  2968                              <1> 	; 16/06/2015
  2969                              <1> 	; 09/06/2015
  2970                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2971                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2972                              <1> 	;
  2973                              <1> 	; 01/08/2013 (mkdir_w check)
  2974                              <1> 
  2975                              <1> 	;push	ax ; 26/04/2013
  2976                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2977                              <1> 	; 03/02/2022
  2978 00004E64 50                  <1> 	push	eax
  2979                              <1> 	; AX = inode number
  2980 00004E65 E8B3FAFFFF          <1> 	call	iget
  2981                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2982                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2983 00004E6A 8B1D[20660000]      <1>         mov     ebx, [u.fofp] 
  2984 00004E70 8B13                <1> 	mov 	edx, [ebx]
  2985                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2986                              <1> 			       ; / in the fsp entry for this file] in r2
  2987 00004E72 0315[34660000]      <1> 	add 	edx, [u.count]	
  2988                              <1> 		; add u.count,r2 / no. of bytes to be written
  2989                              <1> 			       ; / + file offset is put in r2
  2990                              <1> 	; 16/06/2015        
  2991 00004E78 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2992 00004E7E 760F                <1> 	jna	short dskw_0
  2993 00004E80 C705[5F660000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2993 00004E88 0000                <1>
  2994 00004E8A E978E3FFFF          <1> 	jmp	error
  2995                              <1> dskw_0:	
  2996 00004E8F 663B15[08630000]    <1> 	cmp     dx, [i.size]
  2997                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2998                              <1> 		              ; / the file?
  2999 00004E96 760C                <1> 	jna	short dskw_1
  3000                              <1> 		; blos 1f / no, branch
  3001 00004E98 668915[08630000]    <1>         mov     [i.size], dx
  3002                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3003                              <1> 			      ; / file offset + no. of data bytes
  3004 00004E9F E883FBFFFF          <1> 	call	setimod
  3005                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3006                              <1> 		          ; / modified), stuff time of modification into
  3007                              <1> 	          	  ; / core image of i-node
  3008                              <1> dskw_1: ; 1:	
  3009 00004EA4 E80BF9FFFF          <1> 	call	mget
  3010                              <1> 	; EAX = Block number
  3011                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3012                              <1> 			    ; /	the next data byte
  3013                              <1> 	; eax = block number
  3014 00004EA9 8B1D[20660000]      <1> 	mov     ebx, [u.fofp]
  3015 00004EAF 8B13                <1> 	mov	edx, [ebx]
  3016 00004EB1 81E2FF010000        <1> 	and	edx, 1FFh  
  3017                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3018 00004EB7 750C                <1> 	jnz	short dskw_2
  3019                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3020                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3021 00004EB9 813D[34660000]0002- <1> 	cmp	dword [u.count], 512
  3021 00004EC1 0000                <1>
  3022                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3023                              <1> 				  ; / an entire block? (i.e., no. of
  3024 00004EC3 7305                <1> 	jnb	short dskw_3
  3025                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3026                              <1> 			; / Yes, branch. Don't have to read block
  3027                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3028                              <1>    		; / overwritten).
  3029 00004EC5 E80C060000          <1> 	call	dskrd
  3030                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3031                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3032                              <1> dskw_3: ; 3:
  3033                              <1> 	; EAX (r1) = block/sector number
  3034 00004ECA E86B060000          <1> 	call	wslot
  3035                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3036                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3037 00004ECF 803D[71660000]00    <1> 	cmp	byte [u.kcall], 0
  3038 00004ED6 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3039                              <1> 	;
  3040 00004ED8 66833D[6F660000]00  <1> 	cmp	word [u.pcount], 0
  3041 00004EE0 7705                <1> 	ja	short dskw_5
  3042                              <1> dskw_4:
  3043                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3044 00004EE2 E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3045                              <1> dskw_5:
  3046                              <1> 	; EBX (r5) = system (I/O) buffer address
  3047 00004EE7 E87D000000          <1> 	call	sioreg
  3048                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3049                              <1> 			     ; / r1 = address of data, r2 points to location
  3050                              <1> 			     ; / in buffer in which to start writing data
  3051                              <1> 	; ESI = file (user data) offset
  3052                              <1> 	; EDI = sector (I/O) buffer offset
  3053                              <1> 	; ECX = byte count
  3054                              <1> 	;
  3055 00004EEC F3A4                <1>   	rep	movsb
  3056                              <1> 		; movb (r1 )+,(r2)+ 
  3057                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3058                              <1> 		; dec r3 / decrement no. of bytes to be written
  3059                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3060                              <1> 	; 25/07/2015
  3061                              <1> 	; eax = remain bytes in buffer
  3062                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3063 00004EEE 09C0                <1> 	or	eax, eax
  3064 00004EF0 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3065                              <1> dskw_6:
  3066 00004EF2 E850060000          <1> 	call	dskwr
  3067                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3068 00004EF7 833D[34660000]00    <1>         cmp     dword [u.count], 0
  3069                              <1> 		; tst u.count / any more data to write?
  3070 00004EFE 77A4                <1> 	ja	short dskw_1
  3071                              <1> 		; bne 1b / yes, branch
  3072                              <1> 	; 03/08/2013
  3073 00004F00 C605[71660000]00    <1> 	mov	byte [u.kcall], 0
  3074                              <1> 	; 20/09/2013 (;;)
  3075                              <1> 	;pop	ax
  3076                              <1> 	; 03/02/2022
  3077 00004F07 58                  <1> 	pop	eax
  3078 00004F08 C3                  <1> 	retn
  3079                              <1> 	;;jmp 	short dskw_ret 
  3080                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3081                              <1> 
  3082                              <1> cpass: ; / get next character from user area of core and put it in r1
  3083                              <1> 	; 18/10/2015
  3084                              <1> 	; 10/10/2015
  3085                              <1> 	; 10/07/2015
  3086                              <1> 	; 02/07/2015
  3087                              <1> 	; 01/07/2015
  3088                              <1> 	; 24/06/2015
  3089                              <1> 	; 08/06/2015
  3090                              <1> 	; 04/06/2015
  3091                              <1> 	; 20/05/2015
  3092                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3093                              <1> 	;
  3094                              <1> 	; INPUTS -> 
  3095                              <1> 	;     [u.base] = virtual address in user area
  3096                              <1> 	;     [u.count] = byte count (max.)
  3097                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3098                              <1> 	; OUTPUTS -> 
  3099                              <1> 	;     AL = the character which is pointed by [u.base]
  3100                              <1> 	;     zf = 1 -> transfer count has been completed	
  3101                              <1>         ;
  3102                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3103                              <1> 	;
  3104                              <1> 	;
  3105 00004F09 833D[34660000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3106                              <1> 		; tst u.count / have all the characters been transferred
  3107                              <1> 			    ; / (i.e., u.count, # of chars. left
  3108 00004F10 763F                <1> 	jna	short cpass_3
  3109                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3110 00004F12 FF0D[34660000]      <1> 	dec	dword [u.count]
  3111                              <1> 		; dec u.count / no, decrement u.count
  3112                              <1>         ; 19/05/2015 
  3113                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3114                              <1> 	;		      to physical address
  3115 00004F18 66833D[6F660000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3116                              <1> 			     ; 1-4095 --> use previous physical base address
  3117                              <1> 			     ; in [u.pbase]
  3118 00004F20 770E                <1> 	ja	short cpass_1
  3119                              <1> 	; 02/07/2015
  3120 00004F22 833D[67660000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3121 00004F29 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3122                              <1> 	; 08/06/2015 - 10/07/2015
  3123 00004F2B E852FDFFFF          <1> 	call	trans_addr_r
  3124                              <1> cpass_1:
  3125                              <1> 	; 02/07/2015
  3126                              <1> 	; 24/06/2015
  3127 00004F30 66FF0D[6F660000]    <1> 	dec	word [u.pcount]
  3128                              <1> cpass_2: 
  3129                              <1> 	; 10/10/2015
  3130                              <1> 	; 02/07/2015
  3131 00004F37 8B15[6B660000]      <1> 	mov	edx, [u.pbase]
  3132 00004F3D 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3133                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3134                              <1> 				; / by u.base and put it in r1
  3135 00004F3F FF05[38660000]      <1> 	inc	dword [u.nread]
  3136                              <1> 		; inc u.nread / increment no. of bytes transferred
  3137 00004F45 FF05[30660000]      <1> 	inc	dword [u.base]
  3138                              <1> 		; inc u.base / increment the buffer address to point to the
  3139                              <1> 			   ; / next byte
  3140 00004F4B FF05[6B660000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3141                              <1> cpass_3:
  3142 00004F51 C3                  <1> 	retn
  3143                              <1> 		; rts	r0 / next byte
  3144                              <1> 	; 1: 
  3145                              <1> 		; mov (sp)+,r0 
  3146                              <1> 		         ; / put return address of calling routine into r0
  3147                              <1> 		; mov (sp)+,r1 / i-number in r1
  3148                              <1> 		; rts r0 / non-local return
  3149                              <1> cpass_k:
  3150                              <1> 	; 02/07/2015
  3151                              <1> 	; The caller is os kernel 
  3152                              <1> 	; (get sysexec arguments from kernel's memory space)
  3153                              <1> 	;
  3154 00004F52 8B1D[30660000]      <1> 	mov	ebx, [u.base]
  3155 00004F58 66C705[6F660000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3155 00004F60 10                  <1>
  3156 00004F61 891D[6B660000]      <1> 	mov	[u.pbase], ebx
  3157 00004F67 EBCE                <1> 	jmp	short cpass_2
  3158                              <1> 	
  3159                              <1> sioreg: 
  3160                              <1> 	; 25/07/2015
  3161                              <1> 	; 18/07/2015
  3162                              <1> 	; 02/07/2015
  3163                              <1> 	; 17/06/2015
  3164                              <1> 	; 09/06/2015
  3165                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3166                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3167                              <1> 	;
  3168                              <1> 	; INPUTS -> 
  3169                              <1> 	;     EBX = system buffer (data) address (r5)
  3170                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3171                              <1> 	;     [u.base] = virtual address of the user buffer
  3172                              <1> 	;     [u.pbase] = physical address of the user buffer
  3173                              <1> 	;     [u.count] = byte count
  3174                              <1> 	;     [u.pcount] = byte count within page frame 			
  3175                              <1> 	; OUTPUTS -> 
  3176                              <1> 	;     ESI = user data offset (r1)
  3177                              <1> 	;     EDI = system (I/O) buffer offset (r2)
  3178                              <1> 	;     ECX = byte count (r3)
  3179                              <1> 	;     EAX = remain bytes after byte count within page frame
  3180                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3181                              <1>         ;
  3182                              <1> 	; ((Modified registers:  EDX))
  3183                              <1>  
  3184 00004F69 8B35[20660000]      <1>         mov     esi, [u.fofp]
  3185 00004F6F 8B3E                <1>         mov     edi, [esi]
  3186                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3187 00004F71 89F9                <1> 	mov	ecx, edi
  3188                              <1> 		; mov r2,r3 / and also to r3
  3189 00004F73 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3190                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3191 00004F79 81E7FF010000        <1> 	and	edi, 1FFh
  3192                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3193 00004F7F 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3194                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3195                              <1> 			  ; / where data is to be placed
  3196                              <1>                 ; mov u.base,r1 / address of data is in r1
  3197 00004F81 F7D9                <1> 	neg	ecx
  3198                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3199                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3200 00004F83 3B0D[34660000]      <1> 	cmp	ecx, [u.count]
  3201                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3202                              <1> 			       ; / to be written to the file
  3203 00004F89 7606                <1> 	jna	short sioreg_0
  3204                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3205                              <1> 			 ; / in the file block as the number to be written
  3206 00004F8B 8B0D[34660000]      <1> 	mov	ecx, [u.count]
  3207                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3208                              <1> 			       ; / bytes as the number to be written
  3209                              <1> sioreg_0:
  3210                              <1> 	; 17/06/2015
  3211 00004F91 803D[71660000]00    <1> 	cmp	byte [u.kcall], 0 
  3212 00004F98 7613                <1> 	jna	short sioreg_1
  3213                              <1> 	; 25/07/2015
  3214                              <1> 	; the caller is 'mkdir' or 'namei'
  3215 00004F9A A1[30660000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3216 00004F9F A3[6B660000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3217 00004FA4 66890D[6F660000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3218 00004FAB EB0B                <1> 	jmp	short sioreg_2
  3219                              <1> sioreg_1:
  3220                              <1> 	; 25/07/2015
  3221                              <1> 	; 18/07/2015
  3222                              <1> 	; 09/06/2015 
  3223 00004FAD 0FB715[6F660000]    <1> 	movzx	edx, word [u.pcount]
  3224                              <1> 		; ecx and [u.pcount] are always > 0, here
  3225 00004FB4 39D1                <1> 	cmp	ecx, edx	
  3226 00004FB6 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3227                              <1> sioreg_2: ; 2:
  3228 00004FB8 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3229                              <1> sioreg_3:
  3230 00004FBA 010D[38660000]      <1> 	add 	[u.nread], ecx
  3231                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3232                              <1> 			         ; / during write is put into u.nread
  3233 00004FC0 290D[34660000]      <1> 	sub 	[u.count], ecx
  3234                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3235                              <1> 			       ; / must be written or read
  3236 00004FC6 010D[30660000]      <1> 	add 	[u.base], ecx
  3237                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3238                              <1> 			      ; / data bytes
  3239 00004FCC 010E                <1>         add 	[esi], ecx 
  3240                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3241                              <1> 			       ; / + old file offset
  3242                              <1> 	; 25/07/2015
  3243 00004FCE 8B35[6B660000]      <1> 	mov	esi, [u.pbase]
  3244 00004FD4 66290D[6F660000]    <1> 	sub	[u.pcount], cx
  3245 00004FDB 010D[6B660000]      <1> 	add	[u.pbase], ecx
  3246 00004FE1 C3                  <1>         retn
  3247                              <1> 		; rts r0
  3248                              <1> 		; transfer count > [u.pcount]
  3249                              <1> sioreg_4:
  3250                              <1> 	; 25/07/2015
  3251                              <1> 	; transfer count > [u.pcount] 
  3252                              <1> 	; (ecx > edx)
  3253 00004FE2 89C8                <1> 	mov	eax, ecx
  3254 00004FE4 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3255 00004FE6 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3256 00004FE8 EBD0                <1> 	jmp	short sioreg_3
  2056                                  %include 'u7.s'        ; 18/04/2015
  2057                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS7.INC
  2058                              <1> ; Last Modification: 13/06/2022
  2059                              <1> ; ----------------------------------------------------------------------------
  2060                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2061                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2062                              <1> ;
  2063                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2064                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2065                              <1> ; <Bell Laboratories (17/3/1972)>
  2066                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2067                              <1> ;
  2068                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2069                              <1> ;
  2070                              <1> ; ****************************************************************************
  2071                              <1> ; 14/11/2015
  2072                              <1> 
  2073                              <1> sysmount: ; / mount file system; args special; name
  2074                              <1> 	; 14/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2075                              <1> 	; 12/02/2022
  2076                              <1> 	; 04/02/2022
  2077                              <1> 	; 14/11/2015
  2078                              <1> 	; 24/10/2015
  2079                              <1> 	; 13/10/2015
  2080                              <1> 	; 10/07/2015
  2081                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2082                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2083                              <1> 	;
  2084                              <1> 	; 'sysmount' anounces to the system that a removable 
  2085                              <1> 	; file system has been mounted on a special file.
  2086                              <1> 	; The device number of the special file is obtained vihha
  2087                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2088                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2089                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2090                              <1> 	; to read file system into core, i.e. the first block on the
  2091                              <1> 	; mountable file system is read in. This block is super block
  2092                              <1> 	; for the file system. This call is super user restricted.	
  2093                              <1> 	;
  2094                              <1> 	; Calling sequence:
  2095                              <1> 	;	sysmount; special; name
  2096                              <1> 	; Arguments:
  2097                              <1> 	;	special - pointer to name of special file (device)
  2098                              <1> 	;	name -  pointer to name of the root directory of the
  2099                              <1> 	;		newly mounted file system. 'name' should 
  2100                              <1> 	;		always be a directory.
  2101                              <1> 	; Inputs: - 
  2102                              <1> 	; Outputs: -
  2103                              <1> 	; ...............................................................
  2104                              <1> 	;				
  2105                              <1> 	; Retro UNIX 8086 v1 modification: 
  2106                              <1> 	;       'sysmount' system call has two arguments; so,
  2107                              <1> 	;	* 1st argument, special is pointed to by BX register
  2108                              <1> 	;	* 2nd argument, name is in CX register
  2109                              <1> 	;
  2110                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2111                              <1> 	;	       already modified for IBM PC compatibility and 
  2112                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2113                              <1> 	
  2114                              <1> 	;call	arg2
  2115                              <1> 		; jsr r0,arg2 / get arguments special and name
  2116 00004FEA 891D[28660000]      <1> 	mov	[u.namep], ebx
  2117                              <1> 	; 12/02/2022
  2118                              <1> 	;push	ecx ; directory name
  2119 00004FF0 66833D[F8650000]00  <1> 	cmp	word [mnti], 0
  2120                              <1> 		; tst mnti / is the i-number of the cross device file
  2121                              <1> 			 ; / zero?
  2122                              <1> 	;;ja	error
  2123                              <1>         	; bne errora / no, error
  2124                              <1> 	;ja	sysmnt_err0
  2125                              <1> 	; 04/02/2022
  2126 00004FF8 7605                <1> 	jna	short sysmnt_0
  2127 00004FFA E950010000          <1> 	jmp	sysmnt_err0
  2128                              <1> sysmnt_0:
  2129                              <1> 	; 12/02/2022
  2130 00004FFF 51                  <1> 	push	ecx ; directory name
  2131 00005000 E859010000          <1> 	call	getspl
  2132                              <1> 		; jsr r0,getspl / get special files device number in r1
  2133                              <1> 	; 12/02/2022
  2134 00005005 8F05[28660000]      <1> 	pop	dword [u.namep] ; directory name
  2135                              <1> 	; 13/10/2015
  2136                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2137                              <1> 	; 04/02/2022
  2138 0000500B 29DB                <1> 	sub	ebx, ebx
  2139 0000500D 88C3                <1> 	mov	bl, al
  2140 0000500F F683[8E5D0000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2141 00005016 750F                <1> 	jnz	short sysmnt_1
  2142                              <1> sysmnt_err1:
  2143 00005018 C705[5F660000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2143 00005020 0000                <1>
  2144 00005022 E9E0E1FFFF          <1> 	jmp	error
  2145                              <1> sysmnt_1:
  2146                              <1> 	; 12/02/2022
  2147                              <1> 	;pop	dword [u.namep]
  2148                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2149                              <1> 				  ; / on the device
  2150                              <1> 	; 14/11/2015
  2151 00005027 53                  <1> 	push	ebx ; 13/10/2015
  2152                              <1> 		; mov r1,-(sp) / save the device number
  2153                              <1>         ;
  2154 00005028 E8DBF0FFFF          <1> 	call	namei
  2155                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2156                              <1> 		       ; ax = 0 -> file not found 	
  2157                              <1> 	;jz	error
  2158                              <1> 	;jc	error
  2159                              <1> 		; jsr r0,namei / get the i-number of the file
  2160                              <1>                	; br errora
  2161 0000502D 730F                <1> 	jnc	short sysmnt_2
  2162                              <1> sysmnt_err2:
  2163 0000502F C705[5F660000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2163 00005037 0000                <1>
  2164 00005039 E9C9E1FFFF          <1> 	jmp	error
  2165                              <1> sysmnt_2:	
  2166 0000503E 66A3[F8650000]      <1> 	mov	[mnti], ax
  2167                              <1>         	; mov r1,mnti / put it in mnti
  2168                              <1> 
  2169                              <1> 	; 14/05/2022
  2170                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2171 00005044 66A1[F0650000]      <1> 	mov	ax, [ii]
  2172 0000504A 66A3[FA650000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2173                              <1> 
  2174                              <1> 	; 04/02/2022
  2175 00005050 BB[D8780000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2176                              <1> sysmnt_3: ;1:
  2177                              <1>         ;cmp	byte [ebx+1], 0
  2178                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2179                              <1> 			   ; / dismountable device set?
  2180                              <1>         ;jna	short sysmnt_4		
  2181                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2182                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2183                              <1> 	;jmp	short sysmnt_3
  2184                              <1> sysmnt_4:   
  2185 00005055 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2186 00005056 A2[F7650000]        <1> 	mov	[mdev], al
  2187                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2188 0000505B 8803                <1> 	mov	[ebx], al
  2189                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2190                              <1> 			      ; / of the I/O queue entry
  2191                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2192                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2193 0000505D 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2194                              <1> 		; bis $2000,sb1 / set the read bit
  2195                              <1> 	; Retro UNIX 386 v1 modification : 
  2196                              <1> 	;	32 bit block number at buffer header offset 4
  2197 00005062 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2198 00005069 E8A3050000          <1> 	call 	diskio
  2199 0000506E 7345                <1> 	jnc	short sysmnt_5
  2200 00005070 31C0                <1> 	xor 	eax, eax
  2201 00005072 66A3[F8650000]      <1> 	mov	[mnti], ax ; 0
  2202 00005078 A2[F7650000]        <1> 	mov	[mdev], al ; 0
  2203                              <1> 	;mov	[cdev], al ; 0
  2204                              <1> 	; 12/02/2022
  2205 0000507D 803D[72660000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2206 00005084 7508                <1> 	jne	short sysmnt_err3
  2207                              <1> 	; yes, clear [u.brwdev] for next check
  2208                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2209 00005086 FE05[72660000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2210 0000508C EB0A                <1> 	jmp	short sysmnt_err4
  2211                              <1> sysmnt_err3:	; 12/02/2022
  2212                              <1> 	; no, set [u.error] to disk read error
  2213 0000508E C705[5F660000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2213 00005096 0000                <1>
  2214                              <1> sysmnt_err4:
  2215                              <1> 	; 12/02/2022
  2216                              <1> 	; 14/11/2015
  2217 00005098 FEC8                <1> 	dec 	al
  2218 0000509A 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2219 0000509C FEC0                <1> 	inc	al
  2220 0000509E 48                  <1> 	dec	eax
  2221 0000509F 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2222 000050A2 E960E1FFFF          <1> 	jmp	error
  2223                              <1> sysmnt_invd:
  2224                              <1> 	; 12/02/2022
  2225 000050A7 C705[5F660000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2225 000050AF 0000                <1>
  2226                              <1> 				 ;'invalid fs/superblock !' error
  2227 000050B1 30C0                <1> 	xor	al, al
  2228 000050B3 EBE3                <1> 	jmp	short sysmnt_err4
  2229                              <1> 
  2230                              <1> sysmnt_5:
  2231                              <1> 	; 04/02/2022 (BugFix)
  2232                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2233                              <1> 	; (Following check is needed to prevent mounting an
  2234                              <1> 	; invalid valid file system (invalid super block).
  2235                              <1> 	; 
  2236 000050B5 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2237 000050B8 C0E002              <1> 	shl	al, 2 ; 4*index
  2238 000050BB 8B88[725D0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2239                              <1> 	;;shl 	ecx, 3 ; !!!
  2240                              <1> 	; 04/02/2022
  2241 000050C1 C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2242                              <1> 	; ecx = number of free map bytes (required)
  2243                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2244 000050C4 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2245                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2246                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2247 000050C8 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2248                              <1> 			 ; (in sectors), if they are not equal
  2249                              <1> 			 ; the disk to be mounted is an...	
  2250 000050CA 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2251                              <1> 			 ; (which has not got a valid super block)
  2252                              <1> 	;
  2253 000050CC C6430100            <1> 	mov	byte [ebx+1], 0
  2254                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2255                              <1> ;sysmnt_6: ;1:
  2256                              <1> 	;;cmp	byte [sb1+1], 0
  2257                              <1> 		; tstb sb1+1 / done reading?
  2258                              <1>    	;;jna	sysret
  2259                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2260                              <1> 	;;jmp	short sysmnt_6
  2261                              <1> 		;bne 1b / no, wait
  2262                              <1>         	;br sysreta / yes
  2263 000050D0 E952E1FFFF          <1> 	jmp	sysret
  2264                              <1> 
  2265                              <1> sysumount: ; / special dismount file system,
  2266                              <1> 	; 15/05/2022
  2267                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2268                              <1> 	; 04/02/2022
  2269                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2270                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2271                              <1> 	;
  2272                              <1> 	; 04/11/2013
  2273                              <1> 	; 09/07/2013
  2274                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2275                              <1> 	; indicated as an argument is no longer contain a removable
  2276                              <1> 	; file system. 'getspl' gets the device number of the special
  2277                              <1> 	; file. If no file system was mounted on that device an error
  2278                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2279                              <1> 	; to 'sysret'.
  2280                              <1> 	;
  2281                              <1> 	; Calling sequence:
  2282                              <1> 	;	sysmount; special
  2283                              <1> 	; Arguments:
  2284                              <1> 	;	special - special file to dismount (device)
  2285                              <1> 	;
  2286                              <1> 	; Inputs: - 
  2287                              <1> 	; Outputs: -
  2288                              <1> 	; ...............................................................
  2289                              <1> 	;				
  2290                              <1> 	; Retro UNIX 8086 v1 modification: 
  2291                              <1> 	;       'sysumount' system call has one argument; so,
  2292                              <1> 	;	* Single argument, special is pointed to by BX register
  2293                              <1> 	;
  2294                              <1> 	
  2295                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2296                              <1> 	;call	arg
  2297                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2298 000050D5 891D[28660000]      <1>         mov	[u.namep], ebx
  2299 000050DB E87E000000          <1> 	call	getspl
  2300                              <1> 		; jsr r0,getspl / get the device number in r1
  2301                              <1> 	;;;
  2302                              <1> 	; 09/05/2022 - Erdogan Tan
  2303                              <1> 	; (I have added [mnti] check because
  2304                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2305                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2306                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2307                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2308 000050E0 66833D[F8650000]00  <1> 	cmp	word [mnti], 0
  2309 000050E8 7665                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2310                              <1> 	;;;
  2311                              <1> 
  2312 000050EA 3A05[F7650000]      <1> 	cmp	al, [mdev]
  2313                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2314 000050F0 755D                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2315                              <1> 	;jne	error
  2316                              <1>         	; bne errora / no error
  2317 000050F2 30C0                <1> 	xor	al, al ; ah = 0
  2318                              <1> sysumnt_0: ;1:
  2319                              <1>      	; 04/02/2022
  2320                              <1> 	;cmp 	[sb1+1], al ; 0
  2321                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2322                              <1> 	;		   ; / (inhibit bit set)?
  2323                              <1> 	;jna	short sysumnt_1		
  2324                              <1> 	;	; bne 1b / yes, wait
  2325                              <1> 	;call	idle ; (wait for hardware interrupt)
  2326                              <1> 	;jmp	short sysumnt_0
  2327                              <1> sysumnt_1:
  2328                              <1> 	; 15/05/2022
  2329                              <1> 	; change user's current directory to mounting directory
  2330                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2331 000050F4 3805[54660000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2332 000050FA 7643                <1> 	jna	short sysumnt_4
  2333                              <1> 	;;;
  2334                              <1> 	; 15/05/2022
  2335                              <1> 	; It is needed to change the parent process's current
  2336                              <1> 	; directory because shell runs (/etc/umount) 
  2337                              <1> 	; as child process.
  2338 000050FC 31DB                <1> 	xor	ebx, ebx 
  2339 000050FE 8A1D[59660000]      <1> 	mov	bl, [u.uno]
  2340 00005104 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2341 00005106 81C3[42630000]      <1> 	add	ebx, p.ppid-2
  2342 0000510C 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2343 0000510F BE[24630000]        <1> 	mov	esi, p.pid
  2344 00005114 29C9                <1> 	sub	ecx, ecx
  2345 00005116 B110                <1> 	mov	cl, nproc ; 16  
  2346                              <1> sysumnt_2:	
  2347 00005118 66AD                <1> 	lodsw
  2348 0000511A 6639D0              <1> 	cmp	ax, dx
  2349 0000511D 7402                <1> 	je	short sysumnt_3
  2350 0000511F E2F7                <1> 	loop	sysumnt_2
  2351                              <1> sysumnt_3:
  2352 00005121 31C0                <1> 	xor	eax, eax
  2353 00005123 81EE[24630000]      <1> 	sub	esi, p.pid
  2354 00005129 D1E6                <1> 	shl	esi, 1
  2355 0000512B 8B9E[90630000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2356                              <1> 	; ebx points to user (u) structure in upage
  2357 00005131 668B15[F8650000]    <1> 	mov	dx, [mnti]
  2358                              <1> 	;mov	[u.cdir], dx
  2359                              <1> 	;mov	[u.cdrv], al ; 0
  2360 00005138 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2361 0000513C 88434C              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2362                              <1> 	;;;
  2363                              <1> sysumnt_4: 
  2364 0000513F A2[F7650000]        <1> 	mov	[mdev], al ; 0
  2365                              <1> 	     	; clr mntd / no, clear these
  2366 00005144 66A3[F8650000]      <1>    	mov	[mnti], ax ; 0
  2367                              <1>         	; clr mnti
  2368                              <1> 
  2369                              <1> 	;; 15/05/2022
  2370                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2371                              <1> 	;mov	ax, dx  ; [u.cdir]
  2372                              <1> 	;call	iget		
  2373                              <1> 
  2374 0000514A E9D8E0FFFF          <1>         jmp	sysret
  2375                              <1> 		; br sysreta / return
  2376                              <1> 
  2377                              <1> sysmnt_err0:
  2378 0000514F C705[5F660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2378 00005157 0000                <1>
  2379 00005159 E9A9E0FFFF          <1> 	jmp	error
  2380                              <1> 
  2381                              <1> getspl: ; / get device number from a special file name
  2382 0000515E E8A5EFFFFF          <1> 	call	namei
  2383                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2384                              <1> 		       ; ax = 0 -> file not found 	
  2385                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2386                              <1> 	; 04/02/2022
  2387 00005163 7305                <1> 	jnc	short getspl_0
  2388 00005165 E9C5FEFFFF          <1> 	jmp	sysmnt_err2
  2389                              <1> getspl_0:
  2390                              <1> 	;jz	error
  2391                              <1> 	;jc	error
  2392                              <1> 		; jsr r0,namei / get the i-number of the special file
  2393                              <1>                 ; br errora / no such file
  2394 0000516A 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2395                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2396                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2397 0000516E 72DF                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2398                              <1> 	;jc	error
  2399                              <1> 		; ble errora / less than 0?  yes, error
  2400 00005170 6683F805            <1>         cmp	ax, 5 ;
  2401                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2402                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2403                              <1> 	;;ja	error
  2404                              <1>         ;	; bgt errora / yes, error
  2405                              <1>         ; 04/02/2022
  2406 00005174 7600                <1> 	jna	short getspl_retn
  2407                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2408                              <1> ;iopen_retn:
  2409                              <1> ;	retn
  2410                              <1> 		; rts r0 / return with device number in r1
  2411                              <1> ;sysmnt_err0:
  2412                              <1> ;	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2413                              <1> ;	jmp	error
  2414                              <1> 
  2415                              <1> getspl_retn:
  2416                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2417                              <1> 	; 04/02/2022
  2418                              <1> iopen_retn:
  2419 00005176 C3                  <1> 	retn
  2420                              <1> 
  2421                              <1> iopen:
  2422                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2423                              <1> 	;		(Printer initialization)
  2424                              <1> 	; 04/02/2022
  2425                              <1> 	; 19/05/2015
  2426                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2427                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2428                              <1> 	;
  2429                              <1> 	; open file whose i-number is in r1
  2430                              <1> 	; 
  2431                              <1> 	; INPUTS ->
  2432                              <1> 	;    r1 - inode number
  2433                              <1> 	; OUTPUTS ->
  2434                              <1> 	;    file's inode in core	
  2435                              <1> 	;    r1 - inode number (positive)
  2436                              <1> 	;
  2437                              <1> 	; ((AX = R1))
  2438                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2439                              <1> 	;        
  2440                              <1> ; / open file whose i-number is in r1
  2441 00005177 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2442                              <1> 		; tst r1 / write or read access?
  2443 0000517A 7568                <1>         jnz	short iopen_2
  2444                              <1> 		; blt 2f / write, go to 2f
  2445 0000517C B202                <1> 	mov	dl, 2 ; read access
  2446 0000517E E86EF8FFFF          <1> 	call	access
  2447                              <1>         	; jsr r0,access; 2 
  2448                              <1> 	; / get inode into core with read access
  2449                              <1> 	; DL=2
  2450                              <1> iopen_0:
  2451 00005183 6683F828            <1>         cmp	ax, 40
  2452                              <1> 		; cmp r1,$40. / is it a special file
  2453 00005187 77ED                <1>         ja	short iopen_retn
  2454                              <1> 		; bgt 3f / no. 3f
  2455                              <1> 	; 04/02/2022
  2456 00005189 50                  <1> 	push	eax
  2457                              <1> 	;push	ax
  2458                              <1> 		; mov r1,-(sp) / yes, figure out
  2459 0000518A 0FB6D8              <1> 	movzx	ebx, al
  2460 0000518D C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2461                              <1> 	;shl	bx, 2
  2462                              <1> 		; asl r1
  2463 00005190 81C3[94510000]      <1>         add     ebx, iopen_1 - 4
  2464 00005196 FF23                <1> 	jmp	dword [ebx]
  2465                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2466                              <1> iopen_1: ; 1:
  2467 00005198 [FC510000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2468                              <1>  		 ;otty / tty ; r1=2
  2469                              <1>         	 ;oppt / ppt ; r1=4
  2470 0000519C [B4520000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2471                              <1> 		 ;sret / mem ; r1=6
  2472                              <1> 		 ;sret / rf0
  2473                              <1>         	 ;sret / rk0
  2474                              <1>         	 ;sret / tap0
  2475                              <1>         	 ;sret / tap1
  2476                              <1>         	 ;sret / tap2
  2477                              <1>         	 ;sret / tap3
  2478                              <1>         	 ;sret / tap4
  2479                              <1>         	 ;sret / tap5
  2480                              <1>         	 ;sret / tap6
  2481                              <1>         	 ;sret / tap7
  2482 000051A0 [B4520000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2483 000051A4 [B4520000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2484 000051A8 [B4520000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2485 000051AC [B4520000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2486 000051B0 [B4520000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2487 000051B4 [B4520000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2488                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2489                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2490                              <1> 	; 13/06/2022 - (lpt_init)
  2491 000051B8 [80530000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2492 000051BC [0D520000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2493                              <1> 		 ;ocvt / tty0
  2494 000051C0 [0D520000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2495                              <1> 		 ;ocvt / tty1
  2496 000051C4 [0D520000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2497                              <1> 		 ;ocvt / tty2
  2498 000051C8 [0D520000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2499                              <1> 		 ;ocvt / tty3
  2500 000051CC [0D520000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2501                              <1> 		 ;ocvt / tty4
  2502 000051D0 [0D520000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2503                              <1> 		 ;ocvt / tty5
  2504 000051D4 [0D520000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2505                              <1> 		 ;ocvt / tty6
  2506 000051D8 [0D520000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2507                              <1> 		 ;ocvt / tty7
  2508 000051DC [0D520000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2509                              <1> 		 ;error / crd
  2510 000051E0 [0D520000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2511                              <1> 
  2512                              <1> iopen_2: ; 2: / check open write access
  2513 000051E4 66F7D8              <1> 	neg	ax
  2514                              <1> 		; neg r1 / make inode number positive
  2515 000051E7 B201                <1> 	mov	dl, 1 ; write access
  2516 000051E9 E803F8FFFF          <1> 	call	access
  2517                              <1> 		; jsr r0,access; 1 / get inode in core
  2518                              <1> 	; DL=1
  2519                              <1> 	; 04/02/2022
  2520 000051EE F605[05630000]40    <1> 	test	byte [i.flgs+1], 40h
  2521                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2522                              <1>  		; bit $40000,i.flgs / is it a directory?
  2523 000051F5 748C                <1> 	jz	short iopen_0
  2524                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2525                              <1> 	;jmp	error ; permission denied !
  2526 000051F7 E953FFFFFF          <1> 	jmp	sysmnt_err0
  2527                              <1> 	;;jnz	error		
  2528                              <1>        		; bne 2f / yes, transfer (error)
  2529                              <1>         ;;jmp	short iopen_0
  2530                              <1> 	;cmp	ax, 40
  2531                              <1> 		; cmp r1,$40. / no, is it a special file?
  2532                              <1>         ;ja	short iopen_2
  2533                              <1> 		; bgt 3f / no, return
  2534                              <1> 	;push	ax
  2535                              <1> 		; mov r1,-(sp) / yes
  2536                              <1> 	;movzx	ebx, al
  2537                              <1> 	;shl	bx, 1
  2538                              <1> 		; asl r1
  2539                              <1> 	;add	ebx, ipen_3 - 2
  2540                              <1> 	;jmp	dword [ebx]
  2541                              <1> 		; jmp *1f-2(r1) / figure out 
  2542                              <1> 			; / which special file it is and transfer
  2543                              <1> ;iopen_3: ; 1:
  2544                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2545                              <1>  		 ;otty / tty ; r1=2
  2546                              <1>         	 ;leadr / ppt ; r1=4
  2547                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2548                              <1> 		 ;sret / mem ; r1=6
  2549                              <1> 		 ;sret / rf0
  2550                              <1>         	 ;sret / rk0
  2551                              <1>         	 ;sret / tap0
  2552                              <1>         	 ;sret / tap1
  2553                              <1>         	 ;sret / tap2
  2554                              <1>         	 ;sret / tap3
  2555                              <1>         	 ;sret / tap4
  2556                              <1>         	 ;sret / tap5
  2557                              <1>         	 ;sret / tap6
  2558                              <1>         	 ;sret / tap7
  2559                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2560                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2561                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2562                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2563                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2564                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2565                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2566                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2567                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2568                              <1> 		 ;ocvt / tty0
  2569                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2570                              <1> 		 ;ocvt / tty1
  2571                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2572                              <1> 		 ;ocvt / tty2
  2573                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2574                              <1> 		 ;ocvt / tty3
  2575                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2576                              <1> 		 ;ocvt / tty4
  2577                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2578                              <1> 		 ;ocvt / tty5
  2579                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2580                              <1> 		 ;ocvt / tty6
  2581                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2582                              <1> 		 ;ocvt / tty7
  2583                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2584                              <1> 		 ;/ ejec / lpr
  2585                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2586                              <1> 
  2587                              <1> otty: ;/ open console tty for reading or writing
  2588                              <1> 	; 03/03/2022
  2589                              <1> 	; 02/03/2022
  2590                              <1> 	; 27/02/2022
  2591                              <1> 	; 23/02/2022
  2592                              <1> 	; 22/02/2022
  2593                              <1> 	; 04/02/2022
  2594                              <1> 	; 16/11/2015
  2595                              <1> 	; 12/11/2015
  2596                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2597                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2598                              <1> 	; 16/07/2013
  2599                              <1> 	; Retro UNIX 8086 v1 modification:
  2600                              <1> 	;  If a tty is open for read or write by
  2601                              <1> 	;     a process (u.uno), only same process can open
  2602                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2603                              <1> 	;
  2604                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2605                              <1> 	;
  2606 000051FC 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2607 00005203 8A83[63630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2608                              <1> 	; 13/01/2014
  2609                              <1> 	;jmp	short ottyp
  2610                              <1> 	; 23/02/2022
  2611 00005209 88C4                <1> 	mov	ah, al
  2612 0000520B EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2613                              <1> ocvt:
  2614 0000520D 2C0A                <1> 	sub	al, 10
  2615                              <1> 	; 04/02/2022
  2616 0000520F 31DB                <1> 	xor	ebx, ebx
  2617                              <1> ottyp:
  2618                              <1> 	; 23/02/2022
  2619 00005211 B4FF                <1> 	mov	ah, 0FFh
  2620                              <1> ottypc:
  2621                              <1> 	; 03/03/2022
  2622                              <1> 	; 23/02/2022
  2623                              <1> 	; 22/02/2022
  2624                              <1> 	; 12/02/2022
  2625                              <1> 	; 04/02/2022
  2626                              <1> 	; 16/11/2015
  2627                              <1> 	; 12/11/2015
  2628                              <1> 	; 18/05/2015 (32 bit modifications)
  2629                              <1> 	; 06/12/2013 - 13/07/2014
  2630 00005213 88C6                <1> 	mov	dh, al ; tty number
  2631                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2632                              <1> 	; 04/02/2022
  2633 00005215 88C3                <1> 	mov	bl, al
  2634 00005217 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2635                              <1> 	; 26/01/2014	
  2636 00005219 81C3[94620000]      <1> 	add 	ebx, ttyl
  2637 0000521F 668B0B              <1> 	mov 	cx, [ebx]
  2638                              <1> 		   ; CL = lock value (0 or process number)
  2639                              <1> 		   ; CH = open count 
  2640 00005222 20C9                <1> 	and 	cl, cl
  2641                              <1> 	; 13/01/2014
  2642                              <1> 	;jz 	short otty_ret
  2643                              <1> 	; 04/02/2022
  2644 00005224 7447                <1> 	jz 	short ottys_0
  2645                              <1> 	;
  2646                              <1> 	; 16/11/2015
  2647 00005226 3A0D[59660000]      <1> 	cmp 	cl, [u.uno]
  2648 0000522C 746E                <1> 	je	short ottys_3
  2649                              <1> 	;
  2650                              <1> 	; 23/02/2022
  2651                              <1> 	; (is it the console tty of the current process?)
  2652                              <1> 	; ((fast check/permit for console tty open function))
  2653 0000522E 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2654 00005230 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2655                              <1> 	;
  2656                              <1> 	; 22/02/2022
  2657                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2658                              <1> 	;shl 	bl, 1
  2659                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2660                              <1> 	;;movzx ebx, byte [u.uno]
  2661                              <1> 	;mov	bl, [u.uno]
  2662                              <1> 	;shl 	bl, 1
  2663                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2664                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2665                              <1> 	; 22/02/2022 (BugFix) ; *
  2666 00005232 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2667 00005235 D1E6                <1> 	shl 	esi, 1
  2668 00005237 668B86[22630000]    <1> 	mov 	ax, [esi+p.pid-2]
  2669 0000523E 96                  <1> 	xchg	esi, eax
  2670 0000523F A0[59660000]        <1> 	mov	al, [u.uno]
  2671 00005244 D0E0                <1> 	shl 	al, 1
  2672 00005246 663BB0[42630000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2673 0000524D 744D                <1> 	je 	short ottys_3 ; *
  2674                              <1> 	; 23/02/2022
  2675                              <1> 	; check console tty of the process
  2676                              <1> 	; (open permission must be given if the -requested- tty is
  2677                              <1> 	;  console tty of current process)
  2678 0000524F D0E8                <1> 	shr	al, 1
  2679 00005251 38B0[63630000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2680 00005257 7443                <1> 	je 	short ottys_3
  2681                              <1> 	;
  2682                              <1> 	; the tty is locked by another process
  2683                              <1> 	; except the parent process (p.ppid)
  2684                              <1>         ;
  2685                              <1> 	; 09/02/2022
  2686                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2687                              <1> 	;		; permission denied ! error
  2688                              <1> otty_err: ; 13/01/2014
  2689                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2690                              <1> 	;;jnz	error
  2691                              <1> 	; 04/02/2022
  2692                              <1> 	;jz	short otty_stc_retn
  2693                              <1> 	;jmp	error
  2694                              <1> 	; 12/02/2022
  2695 00005259 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2696 0000525C 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2697                              <1> 	; iopen (dl=1 or dl=2)
  2698 0000525E C705[5F660000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2698 00005266 0000                <1>
  2699                              <1> 			; permission denied ! error
  2700 00005268 E99ADFFFFF          <1> 	jmp	error
  2701                              <1> ;otty_stc_retn:
  2702                              <1> 	;stc
  2703                              <1> 	;retn
  2704                              <1> ottys_0:
  2705                              <1> 	; 04/02/2022
  2706                              <1> otty_ret: 
  2707                              <1> 	; 13/01/2014
  2708 0000526D 80FE07              <1> 	cmp 	dh, 7
  2709 00005270 7624                <1> 	jna	short ottys_2
  2710                              <1> 	; 16/11/2015
  2711                              <1> com_port_check:
  2712 00005272 BE[B2620000]        <1> 	mov	esi, com1p
  2713 00005277 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2714 0000527A 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2715 0000527C 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2716                              <1> ottys_1:
  2717                              <1> 	; 12/11/2015
  2718 0000527D 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2719 00005280 7714                <1> 	ja	short com_port_ready
  2720                              <1> 	;
  2721                              <1> 	; 12/02/2022
  2722 00005282 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2723 00005285 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2724 00005287 C705[5F660000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2724 0000528F 0000                <1>
  2725                              <1> 			   ; device not ready ! error
  2726                              <1> 	;jmp	short otty_err
  2727 00005291 E971DFFFFF          <1> 	jmp	error
  2728                              <1> com_port_ready:
  2729                              <1> ottys_2:
  2730                              <1> 	; 02/03/2022
  2731                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2732                              <1> 	;jnz	short ottys_3
  2733 00005296 8A0D[59660000]      <1> 	mov	cl, [u.uno]
  2734                              <1> ottys_3:
  2735 0000529C FEC5                <1> 	inc 	ch
  2736 0000529E 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2737                              <1> 	; 06/12/2013
  2738 000052A1 FEC6                <1> 	inc	dh	; tty number + 1
  2739 000052A3 BB[40660000]        <1> 	mov	ebx, u.ttyp
  2740                              <1> 	; 13/01/2014
  2741 000052A8 F6C202              <1> 	test	dl, 2	; open for read sign
  2742 000052AB 7501                <1> 	jnz	short ottys_4
  2743 000052AD 43                  <1> 	inc	ebx
  2744                              <1> ottys_4:
  2745                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2746 000052AE 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2747                              <1> 	; 27/02/2022
  2748 000052B0 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2749 000052B2 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2750                              <1> sret:
  2751                              <1> 	;pop 	ax
  2752                              <1> 	; 04/02/2022
  2753 000052B4 58                  <1> 	pop	eax
  2754                              <1> otty_retn:	; 12/02/2022
  2755                              <1> iclose_retn:	
  2756 000052B5 C3                  <1> 	retn
  2757                              <1> 
  2758                              <1> 	;
  2759                              <1> 	; Original UNIX v1 'otty' routine:
  2760                              <1> 	;	
  2761                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2762                              <1>         ;                 / reader status reg
  2763                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2764                              <1>         ;                 / punch status reg
  2765                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2766                              <1>         ;                          / console tty buffer
  2767                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2768                              <1>         ;            / console tty
  2769                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2770                              <1>         ;             / buffer header
  2771                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2772                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2773                              <1>         ;                 / tty
  2774                              <1>         ;br     sret / ?
  2775                              <1> ;sret:
  2776                              <1> 		; clr *$ps / set processor priority to zero
  2777                              <1> ;	pop	ax
  2778                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2779                              <1> ;3:
  2780                              <1> ;	retn
  2781                              <1>         	; rts r0
  2782                              <1> 	
  2783                              <1> ;ocvt:	; < open tty >
  2784                              <1> 	; 13/01/2014
  2785                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2786                              <1> 	; 24/09/2013 consistency check -> ok
  2787                              <1> 	; 16/09/2013
  2788                              <1> 	; 03/09/2013
  2789                              <1> 	; 27/08/2013
  2790                              <1> 	; 16/08/2013
  2791                              <1> 	; 16/07/2013
  2792                              <1> 	; 27/05/2013
  2793                              <1> 	; 21/05/2013
  2794                              <1> 	;
  2795                              <1> 	; Retro UNIX 8086 v1 modification !
  2796                              <1> 	; 
  2797                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2798                              <1> 	;		(exactly different than this one)
  2799                              <1> 	;	was in 'u9.s' file.
  2800                              <1> 	;
  2801                              <1> 	; 16/07/2013
  2802                              <1> 	; Retro UNIX 8086 v1 modification:
  2803                              <1> 	;  If a tty is open for read or write by
  2804                              <1> 	;     a process (u.uno), only same process can open
  2805                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2806                              <1> 	;
  2807                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2808                              <1> 
  2809                              <1> 	; 16/09/2013
  2810                              <1> 	; sub 	al, 10
  2811                              <1> 	
  2812                              <1> 	; 06/12/2013
  2813                              <1> 	;cmp	al, 7
  2814                              <1>         ;jna     short ottyp
  2815                              <1> 	; 13/01/2014
  2816                              <1> 	;jmp	short ottyp
  2817                              <1> 
  2818                              <1> 
  2819                              <1> ;oppt: / open paper tape for reading or writing
  2820                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2821                              <1> ;        tstb   pptiflg / is file already open
  2822                              <1> ;        bne    2f / yes, branch
  2823                              <1> ;1:
  2824                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2825                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2826                              <1> ;               br .+4 / for paper tape input and place in free list
  2827                              <1> ;        br     1b
  2828                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2829                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2830                              <1> ;        br     sret
  2831                              <1> ;2:
  2832                              <1> ;        jmp    error / file already open
  2833                              <1> 
  2834                              <1> iclose: 
  2835                              <1> 	; 04/02/2022
  2836                              <1> 	; 19/05/2015
  2837                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2838                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2839                              <1> 	;
  2840                              <1> 	; close file whose i-number is in r1
  2841                              <1> 	; 
  2842                              <1> 	; INPUTS ->
  2843                              <1> 	;    r1 - inode number
  2844                              <1> 	; OUTPUTS ->
  2845                              <1> 	;    file's inode in core	
  2846                              <1> 	;    r1 - inode number (positive)
  2847                              <1> 	;
  2848                              <1> 	; ((AX = R1))
  2849                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2850                              <1> 	;        
  2851                              <1> ;/ close file whose i-number is in r1
  2852 000052B6 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2853 000052B8 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2854                              <1> 		; tst r1 / test i-number
  2855                              <1>         ;jnz	short iclose_2
  2856                              <1> 		; blt 2f / if neg., branch
  2857 000052BB 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2858                              <1> 	; 16/07/2013 
  2859 000052BD 66F7D8              <1> 	neg	ax ; make it positive
  2860                              <1> 	; 12/01/2014
  2861 000052C0 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2862                              <1> iclose_0:
  2863 000052C2 6683F828            <1> 	cmp	ax, 40
  2864                              <1> 		; cmp r1,$40. / is it a special file
  2865 000052C6 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2866                              <1> 		; bgt 3b / no, return
  2867                              <1> 	; 12/01/2014
  2868                              <1> 	; DL=2 -> special file was opened for reading
  2869                              <1> 	; DL=1 -> special file was opened for writing
  2870                              <1> 	; 04/02/2022
  2871 000052C8 50                  <1> 	push	eax
  2872                              <1> 	;push	ax
  2873                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2874 000052C9 0FB6D8              <1> 	movzx	ebx, al
  2875                              <1> 	; 04/02/2022
  2876 000052CC C0E302              <1> 	shl	bl, 2
  2877                              <1> 	;shl	bx, 2
  2878                              <1> 		; asl r1
  2879 000052CF 81C3[D3520000]      <1> 	add	ebx, iclose_1 - 4
  2880 000052D5 FF23                <1> 	jmp	dword [ebx]
  2881                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2882                              <1> iclose_1 :
  2883 000052D7 [23530000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2884 000052DB [7E530000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2885 000052DF [7E530000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2886 000052E3 [7E530000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2887 000052E7 [7E530000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2888 000052EB [7E530000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2889 000052EF [7E530000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2890 000052F3 [7E530000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2891 000052F7 [7E530000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2892                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2893                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2894 000052FB [32530000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2895 000052FF [32530000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2896 00005303 [32530000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2897 00005307 [32530000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2898 0000530B [32530000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2899 0000530F [32530000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2900 00005313 [32530000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2901 00005317 [32530000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2902 0000531B [32530000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2903 0000531F [32530000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2904                              <1> 
  2905                              <1> 	; 1:
  2906                              <1> 	;        ctty   / tty
  2907                              <1> 	;        cppt   / ppt
  2908                              <1> 	;        sret   / mem
  2909                              <1> 	;        sret   / rf0
  2910                              <1> 	;        sret   / rk0
  2911                              <1> 	;        sret   / tap0
  2912                              <1> 	;        sret   / tap1
  2913                              <1> 	;        sret   / tap2
  2914                              <1> 	;        sret   / tap3
  2915                              <1> 	;        sret   / tap4
  2916                              <1> 	;        sret   / tap5
  2917                              <1> 	;        sret   / tap6
  2918                              <1> 	;        sret   / tap7
  2919                              <1> 	;        ccvt   / tty0
  2920                              <1> 	;        ccvt   / tty1
  2921                              <1> 	;        ccvt   / tty2
  2922                              <1> 	;        ccvt   / tty3
  2923                              <1> 	;        ccvt   / tty4
  2924                              <1> 	;        ccvt   / tty5
  2925                              <1> 	;        ccvt   / tty6
  2926                              <1> 	;        ccvt   / tty7
  2927                              <1> 	;        error / crd
  2928                              <1> 
  2929                              <1> ;iclose_2: ; 2: / negative i-number
  2930                              <1> 	;neg	ax
  2931                              <1> 		;neg r1 / make it positive
  2932                              <1> 	;cmp	ax, 40
  2933                              <1> 		;cmp r1,$40. / is it a special file?
  2934                              <1>         ;ja	short @b
  2935                              <1> 		;bgt    3b / no. return
  2936                              <1> 	;push	ax
  2937                              <1> 		;mov r1,-(sp)
  2938                              <1> 	;movzx	ebx, al
  2939                              <1> 	;shl	bx, 1
  2940                              <1> 		;asl r1 / yes. compute jump address and transfer
  2941                              <1> 	;add	ebx, iclose_3 - 2
  2942                              <1> 	;jmp	dword [ebx]
  2943                              <1> 		;jmp *1f-2(r1) / figure out 
  2944                              <1> ;iclose_3:
  2945                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2946                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2947                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2948                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2949                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2950                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2951                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2952                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2953                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2954                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2955                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2956                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2957                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2958                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2959                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2960                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2961                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2962                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2963                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2964                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2965                              <1> 	
  2966                              <1> 	;1:
  2967                              <1> 	;      	ctty   / tty
  2968                              <1> 	;       leadr  / ppt
  2969                              <1> 	;       sret   / mem
  2970                              <1> 	;       sret   / rf0
  2971                              <1> 	;       sret   / rk0
  2972                              <1> 	;       sret   / tap0
  2973                              <1> 	;       sret   / tap1
  2974                              <1> 	;       sret   / tap2
  2975                              <1> 	;       sret   / tap3
  2976                              <1> 	;       sret   / tap4
  2977                              <1> 	;       sret   / tap5
  2978                              <1> 	;       sret   / tap6
  2979                              <1> 	;       sret   / tap7
  2980                              <1> 	;       ccvt   / tty0
  2981                              <1> 	;       ccvt   / tty1
  2982                              <1> 	;       ccvt   / tty2
  2983                              <1> 	;       ccvt   / tty3
  2984                              <1> 	;       ccvt   / tty4
  2985                              <1> 	;       ccvt   / tty5
  2986                              <1> 	;       ccvt   / tty6
  2987                              <1> 	;       ccvt   / tty7
  2988                              <1> 	;/       ejec / lpr
  2989                              <1> 
  2990                              <1> ctty: ; / close console tty
  2991                              <1> 	; 25/02/2022
  2992                              <1> 	; 12/02/2022
  2993                              <1> 	; 05/02/2022
  2994                              <1> 	; 04/02/2022
  2995                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2996                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2997                              <1> 	;
  2998                              <1> 	; Retro UNIX 8086 v1 modification !
  2999                              <1> 	; (DL = 2 -> it is open for reading)
  3000                              <1> 	; (DL = 1 -> it is open for writing)
  3001                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3002                              <1> 	;
  3003                              <1> 	; 06/12/2013
  3004 00005323 0FB61D[59660000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3005 0000532A 8A83[63630000]      <1>         mov     al, [ebx+p.ttyc-1]
  3006                              <1> 	; 13/01/2014
  3007                              <1> 	;jmp	short cttyp
  3008                              <1> 	; 05/02/2022
  3009 00005330 EB04                <1> 	jmp	short ctty_0
  3010                              <1> ccvt:
  3011 00005332 2C0A                <1> 	sub 	al, 10
  3012                              <1> cttyp:	; (call from sysstty)
  3013                              <1> 	; 08/01/2022
  3014 00005334 31DB                <1> 	xor	ebx, ebx
  3015                              <1> ctty_0:	
  3016                              <1> 	; 18/05/2015 (32 bit modifications)
  3017                              <1> 	; 16/08/2013 - 26/01/2014
  3018                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3019                              <1> 	; 04/02/2022
  3020 00005336 88C3                <1> 	mov	bl, al
  3021 00005338 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3022                              <1> 	; 26/01/2014
  3023 0000533A 81C3[94620000]      <1> 	add 	ebx, ttyl
  3024 00005340 88C6                <1> 	mov 	dh, al ; tty number
  3025 00005342 668B03              <1> 	mov 	ax, [ebx]
  3026                              <1> 		   ; AL = lock value (0 or process number)
  3027                              <1> 		   ; AH = open count 
  3028 00005345 20E4                <1> 	and 	ah, ah
  3029 00005347 7514                <1> 	jnz	short ctty_ret
  3030                              <1>   	; 12/02/2022
  3031 00005349 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3032 0000534C 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3033                              <1> 	; iclose (dl=1 or dl=2)
  3034 0000534E C705[5F660000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3034 00005356 0000                <1>
  3035                              <1> 			; device not open ! error
  3036                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3037 00005358 E9AADEFFFF          <1> 	jmp	error
  3038                              <1> 	; 26/01/2014
  3039                              <1> ctty_ret:
  3040 0000535D FECC                <1> 	dec 	ah ; decrease open count
  3041 0000535F 7502                <1> 	jnz	short ctty_1
  3042 00005361 30C0                <1> 	xor	al, al ; unlock/free tty
  3043                              <1> ctty_1:
  3044 00005363 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3045                              <1> 	;
  3046 00005366 BB[40660000]        <1> 	mov	ebx, u.ttyp
  3047                              <1> 	;test	dl, 1 ; open for write sign
  3048                              <1> 	;jz	short ctty_2
  3049                              <1> 	; 25/02/2022
  3050 0000536B F6C202              <1> 	test	dl, 2 ; open for read sign
  3051 0000536E 7501                <1> 	jnz	short ctty_2
  3052 00005370 43                  <1> 	inc	ebx
  3053                              <1> ctty_2:
  3054 00005371 FEC6                <1> 	inc	dh ; tty number + 1
  3055 00005373 3A33                <1> 	cmp	dh, [ebx]
  3056                              <1> 	;jne	short cret
  3057 00005375 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  3058                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3059 00005377 C60300              <1> 	mov	byte [ebx], 0
  3060                              <1> ctty_3:
  3061                              <1> 	; 12/02/2022
  3062 0000537A 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3063 0000537C 7401                <1> 	jz	short ctty_4
  3064                              <1> cret:
  3065                              <1> 	;pop	ax
  3066                              <1> 	; 05/02/2022
  3067 0000537E 58                  <1> 	pop	eax
  3068                              <1> ctty_stc_retn:	; 12/02/2022
  3069                              <1> ctty_4:
  3070 0000537F C3                  <1> 	retn
  3071                              <1> 
  3072                              <1> ;ctty_err: ; 13/01/2014
  3073                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3074                              <1> ;	jnz	error
  3075                              <1> ;	stc
  3076                              <1> ;	retn
  3077                              <1> 
  3078                              <1> 	; Original UNIX v1 'ctty' routine:
  3079                              <1> 	;	
  3080                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3081                              <1> 	;		;/ point r5 to the console tty buffer
  3082                              <1>         ;decb   (r5) / dec number of processes using console tty
  3083                              <1>         ;br     sret / return via sret
  3084                              <1> 
  3085                              <1> ;ccvt:	; < close tty >
  3086                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3087                              <1> 	;
  3088                              <1> 	; Retro UNIX 8086 v1 modification !
  3089                              <1> 	; 
  3090                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3091                              <1> 	;		(exactly different than this one)
  3092                              <1> 	;	was in 'u9.s' file.
  3093                              <1> 	;
  3094                              <1> 	; DL = 2 -> it is open for reading
  3095                              <1> 	; DL = 1 -> it is open for writing
  3096                              <1> 	;
  3097                              <1> 	; 17/09/2013
  3098                              <1> 	;sub 	al, 10
  3099                              <1> 	;cmp	al, 7
  3100                              <1> 	;jna	short cttyp
  3101                              <1> 	; 13/01/2014
  3102                              <1> 	;jmp	short cttyp
  3103                              <1> 
  3104                              <1> ;cppt: / close paper tape
  3105                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3106                              <1> ;1:
  3107                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3108                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3109                              <1> ;                          / and assign to free list
  3110                              <1> ;               br sret
  3111                              <1> ;        br     1b
  3112                              <1> 
  3113                              <1> ;ejec:	
  3114                              <1> ;	jmp	error
  3115                              <1> ;/ejec:
  3116                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3117                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3118                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3119                              <1> ;/       br     sret / return to caller via 'sret'
  3120                              <1> 
  3121                              <1> ejec:
  3122                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kewrnel v0.2.0.20)
  3123                              <1> 	;	     - Printer Initialization
  3124                              <1> lpt_init:	
  3125                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3126                              <1> 	;
  3127                              <1> 	; Default printer port: 378h ; LPT1
  3128                              <1> 	
  3129 00005380 B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3130                              <1> 	;call	int17h
  3131 00005382 E8C3FAFFFF          <1> 	call	PRNOP
  3132 00005387 7414                <1> 	jz	short lpt_init_ok
  3133                              <1> 	
  3134                              <1> 	; replace error code with 'device not ready' error
  3135                              <1> 	; (this may be better for 'sysopen')
  3136 00005389 B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3137 0000538E A3[5F660000]        <1> 	mov	[u.error], eax
  3138                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3139 00005393 A3[10660000]        <1> 	mov	[u.r0], eax
  3140 00005398 E96ADEFFFF          <1> 	jmp	error ; (better)	
  3141                              <1> 	
  3142                              <1> lpt_init_ok:
  3143                              <1> 	;jmp	short cret
  3144 0000539D 58                  <1> 	pop	eax    ; inode number
  3145 0000539E C3                  <1> 	retn
  3146                              <1> 	
  2057                                  %include 'u8.s'        ; 11/06/2015
  2058                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS8.INC
  2059                              <1> ; Last Modification: 15/07/2022
  2060                              <1> ; ----------------------------------------------------------------------------
  2061                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2062                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2063                              <1> ;
  2064                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2065                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2066                              <1> ; <Bell Laboratories (17/3/1972)>
  2067                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2068                              <1> ;
  2069                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2070                              <1> ;
  2071                              <1> ; ****************************************************************************
  2072                              <1> ; 24/10/2015
  2073                              <1> 
  2074                              <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2075                              <1> ;---------------------------------------------------------------------
  2076                              <1> ; Buffer Header: -8 bytes-
  2077                              <1> ; word 1 - byte 0 - device (disk index) number (0 to 5)
  2078                              <1> ;	   byte 1 - status bits
  2079                              <1> ;	 	bit 0 - valid buffer bit (1 = valid, 0 = invalid, new)
  2080                              <1> ;		bit 1 - write bit (also modified bit)
  2081                              <1> ;		bit 2 - read bit	
  2082                              <1> ;		bit 3 to bit 7 are not used
  2083                              <1> ; word 2 - byte & byte 3 not used
  2084                              <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7:
  2085                              <1> ;		physical block/sector address (32 bit LBA)
  2086                              <1> ;---------------------------------------------------------------------
  2087                              <1> 
  2088                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2089                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2090                              <1> ;; Word 1, byte 0 = device id
  2091                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2092                              <1> ;;          bit 9 = write bit
  2093                              <1> ;;	    bit 10 = read bit	  
  2094                              <1> ;;	    bit 12 = waiting to write bit	
  2095                              <1> ;;	    bit 13 = waiting to read bit
  2096                              <1> ;;	    bit 15 = inhibit bit
  2097                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2098                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2099                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2100                              <1> ;;
  2101                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2102                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2103                              <1> ;;
  2104                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2105                              <1> ;; Word 1, Byte 0 = device id
  2106                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2107                              <1> ;;          bit 9 = write bit
  2108                              <1> ;;	    bit 10 = read bit	  
  2109                              <1> ;;	    bit 12 = waiting to write bit	
  2110                              <1> ;;	    bit 13 = waiting to read bit
  2111                              <1> ;;	    bit 15 = inhibit bit
  2112                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2113                              <1> ;;
  2114                              <1> ;; Original UNIX v1 ->
  2115                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2116                              <1> ;; Original UNIX v1 -> 
  2117                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2118                              <1> ;;
  2119                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2120                              <1> ;;
  2121                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2122                              <1> ;;          0 = fd0
  2123                              <1> ;;	    1 = fd1
  2124                              <1> ;;	    2 = hd0
  2125                              <1> ;;	    3 = hd1
  2126                              <1> ;;	    4 = hd2
  2127                              <1> ;;	    5 = hd3
  2128                              <1> 
  2129                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2130                              <1> 
  2131                              <1> 	; 04/02/2022
  2132                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2133                              <1> 	; 26/04/2013
  2134                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2135                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2136                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2137                              <1> 
  2138                              <1> 	; 04/02/2022
  2139                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2140                              <1> 	; 26/04/2013
  2141                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2142                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2143                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2144                              <1> 
  2145                              <1> bread: 
  2146                              <1> 	; 14/07/2022
  2147                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2148                              <1> 	; 12/02/2022
  2149                              <1> 	; 04/02/2022
  2150                              <1> 	; 14/07/2015
  2151                              <1> 	; 10/07/2015
  2152                              <1> 	; 09/06/2015
  2153                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2154                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2155                              <1> 	;	
  2156                              <1> 	; / read a block from a block structured device
  2157                              <1> 	;
  2158                              <1> 	; INPUTS ->
  2159                              <1> 	;    [u.fofp] points to the block number
  2160                              <1> 	;    ECX = maximum block number allowed on device
  2161                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2162                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2163                              <1> 	;    [u.count]	number of bytes to read in
  2164                              <1> 	; OUTPUTS ->
  2165                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2166                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2167                              <1> 	;
  2168                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX, ESI, EDI))
  2169                              <1> 	;
  2170                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2171                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2172                              <1> 	;	is increased by 1. For example: If user/program request 
  2173                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2174                              <1> 	;  	the next block number just as 512 byte reading is done.
  2175                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2176                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2177                              <1> 	;       enough to keep byte position/offset of the disk), this
  2178                              <1> 	;	defect will not be corrected, user/program must request
  2179                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2180                              <1> 	;       for achieving correct result. In future version(s), 
  2181                              <1> 	;	this defect will be corrected by using different 
  2182                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2183                              <1> 
  2184                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2185                              <1> 			       ; / (only works on tape)
  2186                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2187                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2188                              <1> ;1:
  2189                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2190                              <1> 			    ; / maximum block # allowed on device
  2191                              <1> 		; jnb short @f
  2192                              <1> 		; bhis	1f / yes, 1f (error)
  2193                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2194                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2195                              <1> 		; mov (sp)+,r1 / return block # to r1
  2196                              <1> 		; inc r1 / bump block # to next consecutive block
  2197                              <1> 		; dec (sp) / "2-1-cold" on stack
  2198                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2199                              <1> ;1:
  2200                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2201                              <1> 	;push	ecx ; **
  2202                              <1> 	;26/04/2013
  2203                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2204 0000539F 2C03                <1> 	sub	al, 3
  2205                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2206 000053A1 A2[72660000]        <1> 	mov	[u.brwdev], al
  2207                              <1> 	; 09/06/2015
  2208                              <1> 	;movzx	ebx, al
  2209                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2210                              <1> 	; 04/02/2022 (BugFix)
  2211 000053A6 C0E002              <1> 	shl	al, 2 ; * 4
  2212 000053A9 8B88[725D0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2213                              <1> bread_0:
  2214 000053AF 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2215                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2216                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2217 000053B0 8B1D[20660000]      <1> 	mov	ebx, [u.fofp]
  2218 000053B6 8B03                <1> 	mov	eax, [ebx]
  2219 000053B8 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2220                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2221                              <1> 			       ; / block #
  2222 000053BB 39C8                <1> 	cmp	eax, ecx
  2223                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2224                              <1>        	                     ; / block number allowed
  2225                              <1> 	;jnb	error 	     ; 18/04/2013
  2226                              <1> 		; bhis error10 / yes, error
  2227                              <1> 	; 12/02/2022
  2228                              <1> 	;jb	short bread_1
  2229                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2230                              <1> 	;jmp	error
  2231 000053BD 7342                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2232                              <1> bread_1:
  2233                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2234                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2235                              <1> 	; EAX = Block number (zero based)
  2236                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2237                              <1> preread: ;; call preread
  2238 000053BF BF[72660000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2239 000053C4 E8D4010000          <1> 	call	bufaloc_0 ; 26/04/2013
  2240                              <1> 	;; jc 	error
  2241                              <1> 	; EBX = Buffer (Header) Address -Physical-
  2242                              <1>         ; EAX = Block/Sector number (r1)
  2243                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2244                              <1> 	; 14/03/2013
  2245 000053C9 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2246                              <1>        		; br 1f / branch if block already in a I/O buffer
  2247 000053CB 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2248                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2249 000053D0 E8A0010000          <1> 	call	poke
  2250                              <1>         	; jsr r0,poke / perform the read
  2251                              <1> 	;;jc	error ;2 0/07/2013
  2252                              <1> ; 1:
  2253                              <1>  		; clr *$ps / ps = 0
  2254                              <1>         	; rts r0
  2255                              <1> 	; 12/02/2022
  2256 000053D5 7305                <1> 	jnc	short bread_2
  2257 000053D7 E911010000          <1> 	jmp	dskrd_err
  2258                              <1> 
  2259                              <1> ;; return from preread
  2260                              <1> bread_2:
  2261                              <1> 	; 14/07/2022
  2262                              <1> 	;or	word [ebx], 4000h 
  2263                              <1> 	;	; bis $40000,(r5) 
  2264                              <1> 	;		; / set bit 14 of the 1st word of the I/O buffer
  2265                              <1> bread_3: ; 1:
  2266                              <1> 	; 14/07/2022
  2267                              <1> 	;test	word [ebx], 2400h
  2268                              <1> 	;	; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2269                              <1> 	;jz	short bread_4
  2270                              <1> 	;	; beq 1f / no
  2271                              <1> 	;	; cmp cdev,$1 / disk or drum?
  2272                              <1> 	;	; ble 2f / yes
  2273                              <1> 	;	; tstb uquant / is the time quantum = 0?
  2274                              <1> 	;	; bne 2f / no, 2f
  2275                              <1> 	;	; mov r5,-(sp) / yes, save r5 (buffer address)
  2276                              <1> 	;	; jsr r0,sleep; 31. 
  2277                              <1> 	;		; / put process to sleep in channel 31 (tape)
  2278                              <1> 	;	; mov (sp)+,r5 / restore r5
  2279                              <1> 	;	; br 1b / go back
  2280                              <1> ; 2: / drum or disk
  2281                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2282                              <1> 	;call	idle
  2283                              <1> 	;	; jsr r0,idle; s.wait+2 / wait
  2284                              <1> 	;jmp	short bread_3
  2285                              <1>        	;	; br 1b
  2286                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2287                              <1> 	;and	word [ebx], 0BFFFh ; 1011111111111111b
  2288                              <1> 	;	; bic $40000,(r5) / clear bit 14
  2289                              <1>        	;	; jsr r0,tstdeve / test device for error (tape)
  2290                              <1> 	; 14/07/2022
  2291 000053DC 83C308              <1> 	add	ebx, 8
  2292                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2293                              <1> 	; 09/06/2015
  2294 000053DF 66833D[6F660000]00  <1> 	cmp	word [u.pcount], 0
  2295 000053E7 7705                <1> 	ja	short bread_5
  2296 000053E9 E898F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2297                              <1> bread_5:
  2298                              <1> 	; EBX = system (I/O) buffer address
  2299 000053EE E870000000          <1> 	call	dioreg
  2300                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2301                              <1> 	; esi = start address of the transfer (in the buffer)
  2302                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2303                              <1> 	; ecx = transfer count (in bytes)
  2304                              <1> 	;
  2305                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2306                              <1> ;   / of users data
  2307 000053F3 F3A4                <1> 	rep	movsb
  2308                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2309                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2310                              <1>        		; bne 1b
  2311 000053F5 59                  <1> 	pop	ecx ; **
  2312 000053F6 833D[34660000]00    <1> 	cmp	dword [u.count], 0
  2313                              <1> 		; tst u.count / done
  2314 000053FD 77B0                <1> 	ja	short bread_0 ; 09/06/2015
  2315                              <1>        		; beq 1f / yes, return
  2316                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2317                              <1>        		; br bread / read some more
  2318                              <1> ; 1:
  2319 000053FF 58                  <1> 	pop	eax ; ****
  2320                              <1>        		; mov (sp)+,r0
  2321 00005400 C3                  <1>         retn		; 09/06/2015
  2322                              <1> 	;jmp	ret_ 
  2323                              <1> 		;jmp ret / jump to routine that called readi
  2324                              <1> 
  2325                              <1> 	; 08/02/2022
  2326                              <1> brw_oov_err:
  2327 00005401 C705[5F660000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2327 00005409 0000                <1>
  2328 0000540B E9F7DDFFFF          <1> 	jmp	error
  2329                              <1> 
  2330                              <1> 	; 12/02/2022
  2331                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2332                              <1> 	; 26/04/2013
  2333                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2334                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2335                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2336                              <1> 
  2337                              <1> 	; 12/02/2022				
  2338                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2339                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2340                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2341                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2342                              <1> 
  2343                              <1> bwrite: 
  2344                              <1> 	; 14/07/2022
  2345                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2346                              <1> 	; 12/02/2022
  2347                              <1> 	; 04/02/2022
  2348                              <1> 	; 14/07/2015
  2349                              <1> 	; 10/07/2015
  2350                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2351                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2352                              <1> 	;	
  2353                              <1> 	;; / write on block structured device
  2354                              <1> 	;
  2355                              <1> 	; INPUTS ->
  2356                              <1> 	;    [u.fofp] points to the block number
  2357                              <1> 	;    ECX = maximum block number allowed on device
  2358                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2359                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2360                              <1> 	;    [u.count]	number of bytes to user desires to write
  2361                              <1> 	; OUTPUTS ->
  2362                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2363                              <1> 	;
  2364                              <1> 	; ((Modified registers: EDX, ECX, EBX, ESI, EDI))
  2365                              <1> 	;
  2366                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2367                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2368                              <1> 	;	is increased by 1. For example: If user/program request 
  2369                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2370                              <1> 	;  	the next block number just as 512 byte writing is done.
  2371                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2372                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2373                              <1> 	;       enough to keep byte position/offset of the disk), this
  2374                              <1> 	;	defect will not be corrected, user/program must request
  2375                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2376                              <1> 	;       for achieving correct result. In future version(s), 
  2377                              <1> 	;	this defect will be corrected by using different 
  2378                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2379                              <1> 
  2380                              <1>        		; jsr r0,tstdeve / test the device for an error
  2381                              <1> 	;push	ecx ; **
  2382                              <1> 	;26/04/2013
  2383                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2384 00005410 2C03                <1> 	sub	al, 3
  2385                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2386 00005412 A2[72660000]        <1> 	mov	[u.brwdev], al
  2387                              <1> 	; 09/06/2015
  2388                              <1> 	;movzx	ebx, al
  2389                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2390                              <1> 	; 04/02/2022 (BugFix)
  2391 00005417 C0E002              <1> 	shl	al, 2 ; * 4
  2392 0000541A 8B88[725D0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2393                              <1> bwrite_0:
  2394 00005420 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2395                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2396                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2397 00005421 8B1D[20660000]      <1> 	mov	ebx, [u.fofp]
  2398 00005427 8B03                <1> 	mov	eax, [ebx]       
  2399 00005429 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2400                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2401 0000542C 39C8                <1> 	cmp	eax, ecx
  2402                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2403                              <1>        	                     ; / block number allowed
  2404                              <1> 	;jnb	error	     ; 18/04/2013
  2405                              <1> 		; bhis error10 / yes, error
  2406                              <1>      	; 12/02/2022
  2407                              <1> 	;jb	short bwrite_1
  2408                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2409                              <1> 	;jmp	error
  2410 0000542E 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2411                              <1> bwrite_1:
  2412                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2413                              <1> 		; inc *u.fofp / no, increment block number
  2414                              <1> 	; 09/06/2015 - 10/07/2015
  2415 00005430 66833D[6F660000]00  <1> 	cmp	word [u.pcount], 0
  2416 00005438 7705                <1> 	ja	short bwrite_2
  2417 0000543A E843F8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2418                              <1> bwrite_2:
  2419 0000543F BF[72660000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2420 00005444 E8C5000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2421                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2422                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2423 00005449 E815000000          <1>         call	dioreg
  2424                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2425                              <1> 	; esi = destination address (in the buffer)
  2426                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2427                              <1> 	; ecx = transfer count (in bytes)
  2428                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2429 0000544E 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2430 00005450 F3A4                <1> 	rep	movsb
  2431                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2432                              <1>        		; dec r3 / area to the I/O buffer
  2433                              <1>        		; bne 1b
  2434 00005452 E8F0000000          <1> 	call	dskwr
  2435                              <1> 		; jsr r0,dskwr / write it out on the device
  2436 00005457 59                  <1> 	pop	ecx ; **
  2437 00005458 833D[34660000]00    <1>         cmp     dword [u.count], 0
  2438                              <1> 		; tst u.count / done
  2439 0000545F 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2440                              <1> 		; beq 1f / yes, 1f
  2441                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2442                              <1>        		; br bwrite / go back and write next block
  2443                              <1> ; 1:
  2444 00005461 58                  <1> 	pop	eax ; ****
  2445                              <1>        		; mov (sp)+,r0
  2446 00005462 C3                  <1> 	retn		; 09/06/2015
  2447                              <1>         ;jmp	ret_ 
  2448                              <1> 		; jmp ret / return to routine that called writei
  2449                              <1> ;error10:
  2450                              <1> ;       jmp     error  ; / see 'error' routine
  2451                              <1> 
  2452                              <1> dioreg:
  2453                              <1> 	; 04/02/2022
  2454                              <1> 	; 14/07/2015
  2455                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2456                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2457                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2458                              <1> 	;	
  2459                              <1> 	; bookkeeping on block transfers of data
  2460                              <1> 	;
  2461                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2462                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2463                              <1> 	; 10/07/2015
  2464                              <1> 	; * returns byte offset from beginning of current sector buffer
  2465                              <1> 	; (beginning of data) in ESI
  2466                              <1> 	;
  2467 00005463 8B0D[34660000]      <1> 	mov	ecx, [u.count]
  2468                              <1> 		; mov u.count,r3 / move char count to r3
  2469                              <1>         ; 04/02/2022
  2470 00005469 31D2                <1> 	xor	edx, edx
  2471 0000546B B602                <1> 	mov	dh, 2
  2472                              <1> 	; edx = 512
  2473 0000546D 39D1                <1> 	cmp	ecx, edx ; 512
  2474                              <1> 	;cmp 	ecx, 512
  2475                              <1> 		; cmp r3,$512. / more than 512. char?
  2476 0000546F 7602                <1> 	jna	short dioreg_0
  2477                              <1> 		; blos 1f / no, branch
  2478 00005471 89D1                <1> 	mov	ecx, edx ; 512
  2479                              <1> 	;mov	ecx, 512
  2480                              <1> 		; mov $512.,r3 / yes, just take 512.
  2481                              <1> dioreg_0:
  2482                              <1> 	; 09/06/2015
  2483 00005473 663B0D[6F660000]    <1> 	cmp	cx, [u.pcount]
  2484 0000547A 7607                <1> 	jna	short dioreg_1
  2485 0000547C 668B0D[6F660000]    <1> 	mov	cx, [u.pcount]
  2486                              <1> dioreg_1:
  2487                              <1> ; 1:
  2488 00005483 8B15[30660000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2489                              <1> 	        ; mov u.base,r2 / put users base in r2
  2490 00005489 010D[38660000]      <1> 	add	[u.nread], ecx
  2491                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2492 0000548F 290D[34660000]      <1> 	sub	[u.count], ecx
  2493                              <1> 		; sub r3,u.count / update count
  2494 00005495 010D[30660000]      <1> 	add	[u.base], ecx
  2495                              <1> 		; add r3,u.base / update base
  2496                              <1> 	; 10/07/2015
  2497                              <1> 	; Retro UNIX 386 v1 - modification !
  2498                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2499                              <1> 	; (It will point to next byte position instead of next block no.)
  2500 0000549B 8B35[20660000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2501 000054A1 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2502 000054A3 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2503 000054A5 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2504 000054AA 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2505 000054AC 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2506                              <1> 	; 09/06/2015 - 10/07/2015
  2507 000054AE 66290D[6F660000]    <1> 	sub	[u.pcount], cx
  2508 000054B5 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2509 000054BB 8B3D[6B660000]      <1> 	mov	edi, [u.pbase]
  2510 000054C1 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2511 000054C7 01D7                <1> 	add	edi, edx
  2512 000054C9 893D[6B660000]      <1> 	mov	[u.pbase], edi
  2513 000054CF 010D[6B660000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2514 000054D5 C3                  <1> 	retn
  2515                              <1> 		; rts r0 / return
  2516                              <1> 
  2517                              <1> dskrd:
  2518                              <1> 	; 14/07/2022
  2519                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2520                              <1> 	; 12/02/2022
  2521                              <1> 	; 18/08/2015
  2522                              <1> 	; 02/07/2015
  2523                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2524                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2525                              <1> 	;
  2526                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2527                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2528                              <1> 	; (number specified in r1) in the acquired buffer.
  2529                              <1> 	; If the device is busy at the time dskrd is called,	
  2530                              <1> 	; dskrd calls idle.
  2531                              <1> 	; 
  2532                              <1> 	; INPUTS ->
  2533                              <1> 	;    r1 - block number
  2534                              <1> 	;    cdev - current device number 
  2535                              <1> 	; OUTPUTS ->
  2536                              <1> 	;    r5 - points to first data word in I/O buffer
  2537                              <1> 	;
  2538                              <1> 	; ((AX = R1)) input/output
  2539                              <1> 	; ((BX = R5)) output 
  2540                              <1> 	;
  2541                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI))  
  2542                              <1> 	;
  2543 000054D6 E8B5000000          <1> 	call 	bufaloc
  2544                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2545                              <1> 			       ; / get a free I/O buffer
  2546                              <1> 	;;jc	error ; 20/07/2013
  2547 000054DB 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2548                              <1>        		; br 1f / branch if block already in a I/O buffer
  2549                              <1> 
  2550                              <1> 	; 14/07/2022
  2551                              <1> 	; (buffer header byte 1, bit 2 is disk read bit/flag)
  2552                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2553 000054DD 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2554                              <1>         ;	; bis $2000,(r5) / set bit 10 of word 1 of 
  2555                              <1> 	;	               ; / I/O queue entry for buffer
  2556 000054E2 E88E000000          <1> 	call	poke
  2557                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2558                              <1> 			    ; /	bit 10=1 says read
  2559                              <1> 	; 09/06/2015
  2560                              <1> 	;jnc	short dskrd_1
  2561                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2562                              <1> 	;jmp	error
  2563                              <1> 	; 08/02/2022
  2564 000054E7 7204                <1> 	jc	short dskrd_3
  2565                              <1> dskrd_1: ; 1:
  2566                              <1>        	; 14/07/2022
  2567                              <1> 	;
  2568                              <1> 	;	;clr *$ps
  2569                              <1>        	;test	word [ebx], 2400h
  2570                              <1> 	;	; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2571                              <1> 	;			; / jump to idle
  2572                              <1>        	;jz	short dskrd_2
  2573                              <1> 	;	; beq 1f
  2574                              <1>         ;;;mov   ecx, [s.wait_]
  2575                              <1>        	;call	idle
  2576                              <1> 	;	; jsr r0,idle; s.wait+2
  2577                              <1> 	;jmp 	short dskrd_1
  2578                              <1>        	;	; br 1b
  2579                              <1> dskrd_2: ; 1:
  2580 000054E9 83C308              <1>         add	ebx, 8
  2581                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2582                              <1> 			  ; / just read in
  2583 000054EC C3                  <1>        	retn
  2584                              <1> 		; rts r0
  2585                              <1> dskrd_err: 
  2586                              <1> 	; 08/02/2022
  2587                              <1> 	; (jump from 'bread' error)
  2588                              <1> dskrd_3:	
  2589                              <1> 	; 08/02/2022
  2590 000054ED 803D[72660000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2591 000054F4 7509                <1> 	jne	short dskrd_4 ; no
  2592                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2593 000054F6 C605[72660000]00    <1> 	mov	byte [u.brwdev], 0
  2594 000054FD EB0A                <1> 	jmp	short dskrd_5
  2595                              <1> dskrd_4:
  2596 000054FF C705[5F660000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2596 00005507 0000                <1>
  2597                              <1> dskrd_5:
  2598 00005509 E9F9DCFFFF          <1> 	jmp	error
  2599                              <1> 
  2600                              <1> bwslot:
  2601                              <1> 	; 14/07/2022
  2602                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2603                              <1> 	; 04/02/2022
  2604                              <1> 	; 10/07/2015
  2605                              <1> 	;	If the block/sector is not placed in a buffer
  2606                              <1> 	;	before 'wslot', it must be read before
  2607                              <1> 	;	it is written! (Otherwise transfer counts less
  2608                              <1> 	;	than 512 bytes will be able to destroy existing 
  2609                              <1> 	;	data on disk.)
  2610                              <1> 	;
  2611                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2612                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2613                              <1> 	; Retro UNIX 8086 v1 modification !
  2614                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2615                              <1> 	; INPUT -> EDI - points to device id (in u.brwdev)	
  2616                              <1> 	;	-> EAX = block number
  2617                              <1> 	;
  2618 0000550E E88A000000          <1> 	call	bufaloc_0
  2619 00005513 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2620                              <1> 	; 04/02/2022
  2621                              <1> 	; ebx = buffer header address
  2622                              <1> bwslot_0:
  2623                              <1> 	; 10/07/2015
  2624 00005515 8B35[20660000]      <1> 	mov	esi, [u.fofp]
  2625 0000551B 8B06                <1> 	mov	eax, [esi]
  2626 0000551D 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2627 00005522 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2628                              <1> 		       ; recent disk data must be placed in the buffer
  2629 00005524 813D[34660000]0002- <1> 	cmp	dword [u.count], 512
  2629 0000552C 0000                <1>
  2630 0000552E 730F                <1> 	jnb	short wslot_0	
  2631                              <1> bwslot_1:
  2632 00005530 E8A8FFFFFF          <1> 	call	dskrd_0
  2633                              <1> 	; 04/02/2022
  2634                              <1> 	; ebx = buffer data address = buffer header address + 8
  2635 00005535 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2636 00005538 EB05                <1> 	jmp 	short wslot_0
  2637                              <1> 
  2638                              <1> wslot:
  2639                              <1> 	; 14/07/2022
  2640                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2641                              <1> 	;
  2642                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2643                              <1> 	; 		(32 bit modifications)
  2644                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2645                              <1> 	;
  2646                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2647                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2648                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2649                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2650                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2651                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2652                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2653                              <1> 	;
  2654                              <1> 	; INPUTS ->
  2655                              <1>  	;    r1 - block number
  2656                              <1> 	;    cdev - current (block/disk) device number
  2657                              <1>  	;
  2658                              <1> 	; OUTPUTS ->
  2659                              <1> 	;    bufp - bits 9 and 15 are set, 
  2660                              <1> 	;           the remainder of the word left unchanged
  2661                              <1> 	;    r5 - points to first data word in I/O buffer
  2662                              <1> 	;
  2663                              <1> 	; ((AX = R1)) input/output
  2664                              <1> 	; ((BX = R5)) output 
  2665                              <1> 	;
  2666                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 
  2667                              <1> 
  2668 0000553A E851000000          <1> 	call	bufaloc
  2669                              <1> 	; 10/07/2015
  2670                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2671                              <1>         	; br 1f / word in buffer in r5
  2672                              <1> 	; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2673                              <1>         ; EAX = Block/Sector number (r1)
  2674                              <1> wslot_0: ;1:
  2675                              <1> 	; 14/07/2022
  2676                              <1> 	;
  2677                              <1>      	;test	word [ebx], 2400h
  2678                              <1> 	;	; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2679                              <1> 	;			; / of I/O queue entry
  2680                              <1> 	;jz	short wslot_1
  2681                              <1>         ;       ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2682                              <1> 	;	       ; / or not waiting to read)
  2683                              <1> 	;
  2684                              <1> 	;;mov	ecx, [s.wait_] ; 29/07/2013
  2685                              <1> 	;call	idle
  2686                              <1> 	;	; jsr r0,idle; / if buffer is reading or writing to read,
  2687                              <1>        	;                   ; / idle
  2688                              <1> 	;jmp	short wslot_0
  2689                              <1> 	;	; br 1b / till finished
  2690                              <1> wslot_1: ;1:
  2691                              <1> 	;or	word [ebx], 8200h
  2692                              <1>        	;	; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2693                              <1>         ;			; / (write, inhibit bits)
  2694                              <1> 	;	; clr *$ps / clear processor status
  2695                              <1> 
  2696                              <1> 	; 14/07/2022
  2697                              <1> 	; (set disk write bit/flag)
  2698                              <1> 	;or	word [ebx], 200h	
  2699 0000553F 43                  <1> 	inc	ebx
  2700 00005540 800B02              <1> 	or	byte [ebx], 2
  2701 00005543 83C307              <1> 	add	ebx, 7
  2702                              <1> 
  2703                              <1> 	;add	ebx, 8 ; 11/06/2015
  2704                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2705                              <1> 			  ; / for this block
  2706                              <1> dskwr_1:	; 08/02/2022
  2707 00005546 C3                  <1> 	retn
  2708                              <1> 		; rts r0
  2709                              <1> dskwr:
  2710                              <1> 	; 14/07/2022
  2711                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2712                              <1> 	; 12/02/2022
  2713                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2714                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2715                              <1> 	;
  2716                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2717                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2718                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2719                              <1> 	; previously has supplied all the information required in the
  2720                              <1> 	; I/O queue entry.
  2721                              <1> 	;
  2722                              <1> 	; (Modified registers: ECX, EDX, EBX, ESI, EDI)
  2723                              <1> 	;
  2724                              <1> 	;
  2725 00005547 8B1D[C8650000]      <1> 	mov	ebx, [bufp]
  2726                              <1> 	; 14/07/2022
  2727                              <1> 	;and	word [ebx], 7FFFh ; 0111111111111111b
  2728                              <1> 	;	; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2729                              <1>                                   ; / bottom of queue
  2730                              <1> 	; 14/07/2022
  2731                              <1> 	; (set disk write bit)
  2732                              <1> 	; ('wslot' already sets disk write bit/flag)
  2733                              <1> 	;mov	word [ebx], 200h
  2734                              <1> 
  2735 0000554D E823000000          <1> 	call	poke
  2736                              <1> 	; 09/06/2015
  2737 00005552 73F2                <1> 	jnc	short dskwr_1
  2738                              <1> 	; 12/02/2022
  2739 00005554 803D[72660000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2740 0000555B 7509                <1> 	jne	short dskwr_0 ; no
  2741                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2742 0000555D C605[72660000]00    <1> 	mov	byte [u.brwdev], 0
  2743 00005564 EB0A                <1> 	jmp	short dskwr_2
  2744                              <1> dskwr_0:
  2745 00005566 C705[5F660000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2745 0000556E 0000                <1>
  2746                              <1> dskwr_2:
  2747 00005570 E992DCFFFF          <1> 	jmp	error
  2748                              <1> ;dskwr_1:
  2749                              <1> ;	retn
  2750                              <1> 
  2751                              <1> ;ppoke:
  2752                              <1>        		; mov $340,*$ps
  2753                              <1>        		; jsr r0,poke
  2754                              <1>        		; clr *$ps
  2755                              <1> 		; rts r0
  2756                              <1> poke:
  2757                              <1> 	; 14/07/2022
  2758                              <1> 	;	! Major Modification !
  2759                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2760                              <1> 	;
  2761                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2762                              <1> 	; 24/10/2015
  2763                              <1> 	; 20/08/2015
  2764                              <1> 	; 18/08/2015
  2765                              <1> 	; 02/07/2015
  2766                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2767                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2768                              <1> 	;
  2769                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2770                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2771                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2772                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2773                              <1> 	;
  2774                              <1> 	; Basic I/O functions for all block structured devices
  2775                              <1> 	;
  2776                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2777                              <1> 	;
  2778                              <1> 	; 20/07/2013 modifications
  2779                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2780                              <1> 	; INPUTS -> 
  2781                              <1> 	;        EBX = buffer header address
  2782                              <1> 	; OUTPUTS ->
  2783                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2784                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2785                              <1> 	;		(drive not ready or r/w error!)
  2786                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2787                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2788                              <1> 	;        (also it indicates invalid buffer data)
  2789                              <1> 	
  2790                              <1> 	; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2791                              <1> 	; Buffer header:
  2792                              <1> 	;	byte 0 - device/disk (index) number
  2793                              <1> 	;	byte 1 - status
  2794                              <1> 	;	    before 'poke'	
  2795                              <1> 	;		bit 0 - valid bit 
  2796                              <1> 	;		   (0 for new buffer)
  2797                              <1> 	;		   (1 for existing buffer)	
  2798                              <1> 	;		bit 1 - write (modified) bit, disk write flag
  2799                              <1> 	;		bit 2 - read bit, disk read flag
  2800                              <1> 	;	    after 'poke'
  2801                              <1> 	;		if disk r/w is successed
  2802                              <1> 	;		   bit 0 = 1
  2803                              <1> 	;		   bit 1 = 0
  2804                              <1> 	;		   bit 2 = 0
  2805                              <1> 	;		if disk r/w is failed
  2806                              <1> 	;		   bit 0 = 0 (invalid buffer)
  2807                              <1> 	;		   bit 1 = 0 (write bit)
  2808                              <1> 	;		   bit 2 = 0 (read bit)	
  2809                              <1>  	;
  2810                              <1> 	;	byte 2 & byte 3 - not used
  2811                              <1> 	;	byte 4 to byte 7 - disk block/sector address
  2812                              <1> 	
  2813                              <1> 	; 04/02/2022
  2814 00005575 50                  <1> 	push	eax
  2815 00005576 E896000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2816 0000557B 58                  <1> 	pop	eax
  2817 0000557C 730D                <1> 	jnc	short seta ; 14/07/2022
  2818                              <1> 	
  2819                              <1> 	; 14/07/2022
  2820                              <1> 	; (invalidate buffer)
  2821                              <1> 	
  2822                              <1> 	; 02/07/2015 (32 bit modification)
  2823                              <1> 	; 20/07/2013
  2824 0000557E C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2825                              <1>        		; mov $-1,2(r1) / destroy associativity
  2826 00005585 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2827                              <1> 		; clrb 1(r1) / do not do I/O
  2828                              <1> 	;stc
  2829 0000558A C3                  <1> 	retn
  2830                              <1>         	; rts r0
  2831                              <1> seta: 
  2832 0000558B C6430101            <1> 	mov	byte [ebx+1], 1 ; clear write/read bits, set valid bit
  2833                              <1> 	;clc
  2834 0000558F C3                  <1> 	retn
  2835                              <1> 
  2836                              <1> %if 0
  2837                              <1> 
  2838                              <1> poke:
  2839                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2840                              <1> 	; 24/10/2015
  2841                              <1> 	; 20/08/2015
  2842                              <1> 	; 18/08/2015
  2843                              <1> 	; 02/07/2015
  2844                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2845                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2846                              <1> 	;
  2847                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2848                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2849                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2850                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2851                              <1> 	;
  2852                              <1> 	; Basic I/O functions for all block structured devices
  2853                              <1> 	;
  2854                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2855                              <1> 	;
  2856                              <1> 	; 20/07/2013 modifications
  2857                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2858                              <1> 	; INPUTS -> 
  2859                              <1> 	;        (EBX = buffer header address)
  2860                              <1> 	; OUTPUTS ->
  2861                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2862                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2863                              <1> 	;		(drive not ready or r/w error!)
  2864                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2865                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2866                              <1> 	;        (also it indicates invalid buffer data)
  2867                              <1> 	;
  2868                              <1> 	push	ebx
  2869                              <1>        		; mov r1,-(sp)
  2870                              <1>        		; mov r2,-(sp)
  2871                              <1>        		; mov r3,-(sp)
  2872                              <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2873                              <1> 	;
  2874                              <1> 	; 09/06/2015
  2875                              <1> 	; (permit read/write after a disk R/W error)
  2876                              <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2877                              <1> 	mov	al, 1
  2878                              <1> 	shl	al, cl
  2879                              <1> 	test 	al, [active] ; busy ? (error)
  2880                              <1> 	jz	short poke_0
  2881                              <1> 	not	al
  2882                              <1> 	and	[active], al ; reset busy bit for this device only
  2883                              <1> poke_0:
  2884                              <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2885                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2886                              <1> 					 ; / I/O queue pointer
  2887                              <1> poke_1: ; 1:
  2888                              <1>         sub	esi, 4
  2889                              <1> 	mov	ebx, [esi]
  2890                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2891                              <1> 	mov	ax, [ebx] ; 17/07/2013
  2892                              <1>        	test	ah, 06h
  2893                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2894                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2895                              <1> 			       ; / queue entry
  2896                              <1>         jz      short poke_5
  2897                              <1> 		; beq 2f / branch to 2f if both are clear
  2898                              <1> 	; 31/07/2013
  2899                              <1> 	;test	ah, 0B0h ; (*)
  2900                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2901                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2902                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2903                              <1> 		; bne 2f / branch if any are set
  2904                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2905                              <1>     		; movb (r1),r3 / get device id
  2906                              <1> 	movzx	ecx, al ; 18/08/2015
  2907                              <1> 	;mov	edi, ecx ; 26/04/2013
  2908                              <1> 	xor 	eax, eax ; 0
  2909                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2910                              <1> 		; tstb deverr(r3) / test for errors on this device
  2911                              <1>        	;jna	short poke_2 
  2912                              <1> 		; beq 3f / branch if no errors
  2913                              <1> 	; 02/07/2015
  2914                              <1> 	;dec	eax
  2915                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2916                              <1>        		; mov $-1,2(r1) / destroy associativity
  2917                              <1> 	;shr	eax, 24
  2918                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2919                              <1> 		; clrb 1(r1) / do not do I/O
  2920                              <1> 	;jmp     short poke_5
  2921                              <1>         ;       ; br 2f
  2922                              <1>                 ; rts r0
  2923                              <1> poke_2: ; 3:
  2924                              <1> 	; 02/07/2015
  2925                              <1> 	inc	cl ; 0FFh -> 0
  2926                              <1> 	jz	short poke_5
  2927                              <1> 	inc	al ; mov ax, 1
  2928                              <1> 	dec	cl
  2929                              <1> 	jz	short poke_3
  2930                              <1> 	; 26/04/2013 Modification
  2931                              <1> 	;inc	al ; mov ax, 1
  2932                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2933                              <1> 	;jz	short poke_3 ; cl = 0
  2934                              <1> 	shl	al, cl ; shl ax, cl
  2935                              <1> poke_3:
  2936                              <1> 	;test	[active], ax
  2937                              <1> 	test	[active], al
  2938                              <1> 		; bit $2,active / test disk busy bit
  2939                              <1> 	jnz     short poke_5
  2940                              <1> 		; bne 2f / branch if bit is set
  2941                              <1> 	;or	[active], ax
  2942                              <1> 	or	[active], al
  2943                              <1> 		; bis $2,active / set disk busy bit
  2944                              <1> 	;push	ax
  2945                              <1> 	; 04/02/2022
  2946                              <1> 	push	eax
  2947                              <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2948                              <1> 	;mov    [edi+drv.error], ah
  2949                              <1> 	; 04/02/2022
  2950                              <1> 	pop	eax
  2951                              <1> 	;pop	ax
  2952                              <1> 	jnc	short poke_4 ; 20/07/2013
  2953                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2954                              <1> 	;jna	short poke_4
  2955                              <1> 		; tstb deverr(r3) / test for errors on this device
  2956                              <1>        		; beq 3f / branch if no errors
  2957                              <1> 	; 02/07/2015 (32 bit modification)
  2958                              <1> 	; 20/07/2013
  2959                              <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2960                              <1>        		; mov $-1,2(r1) / destroy associativity
  2961                              <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2962                              <1> 		; clrb 1(r1) / do not do I/O
  2963                              <1> 	jmp     short poke_5
  2964                              <1> poke_4:	; 20/07/2013
  2965                              <1> 	; 17/07/2013
  2966                              <1> 	not 	al 
  2967                              <1> 	and	[active], al ; reset, not busy
  2968                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2969                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2970                              <1> 	mov	ax, [ebx]
  2971                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2972                              <1>         and	ax, 600h
  2973                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2974                              <1> 	and 	word [ebx], 0F9FFh
  2975                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2976                              <1> 	shl	ah, 3
  2977                              <1>        		; rol r3
  2978                              <1>                 ; rol r3
  2979                              <1>                 ; rol r3	
  2980                              <1> 	or	[ebx], ax
  2981                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2982                              <1> 			   ; bits 12 and 13
  2983                              <1> 	call	idle ; 18/01/2014
  2984                              <1> 	;; sti
  2985                              <1> 	;hlt 	; wait for a hardware interrupt
  2986                              <1> 	;; cli
  2987                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2988                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2989                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2990                              <1> 	; method, this procedure will wait for a time according to
  2991                              <1> 	; multi tasking and time sharing concept.
  2992                              <1> 	;
  2993                              <1> 	; 24/10/2015
  2994                              <1> 	;not	ax 
  2995                              <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2996                              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2997                              <1> poke_5: ;2:
  2998                              <1>         cmp     esi, bufp
  2999                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  3000                              <1>                             ; / has been scanned
  3001                              <1> 	ja      short poke_1
  3002                              <1>                ; bhi 1b
  3003                              <1> 	; 24/03/2013
  3004                              <1>        		; mov (sp)+,r3
  3005                              <1>        		; mov (sp)+,r2
  3006                              <1>        		; mov (sp)+,r1
  3007                              <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  3008                              <1> 	pop 	ebx
  3009                              <1> 	; 02/07/2015 (32 bit modification)
  3010                              <1> 	; 20/07/2013
  3011                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  3012                              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  3013                              <1> 	;	
  3014                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  3015                              <1> 	; or written succesfully; even if an error occurs while
  3016                              <1> 	; reading to or writing from other buffers. 20/07/2013
  3017                              <1> 	;
  3018                              <1> 	; 09/06/2015
  3019                              <1> 	cmc
  3020                              <1> 	retn
  3021                              <1>                 ; rts r0
  3022                              <1> %endif
  3023                              <1> 
  3024                              <1> bufaloc:
  3025                              <1> 	; 15/07/2022
  3026                              <1> 	; 14/07/2022
  3027                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  3028                              <1> 	; 04/02/2022
  3029                              <1> 	; 20/08/2015
  3030                              <1> 	; 19/08/2015
  3031                              <1> 	; 02/07/2015
  3032                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3033                              <1> 	;	     (32 bit modifications)	
  3034                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  3035                              <1> 	;
  3036                              <1> 	; bufaloc - Block device I/O buffer allocation
  3037                              <1> 	; 
  3038                              <1> 	; INPUTS ->
  3039                              <1> 	;    r1 - block number
  3040                              <1> 	;    cdev - current (block/disk) device number
  3041                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  3042                              <1> 	; OUTPUTS ->
  3043                              <1> 	;    r5 - pointer to buffer allocated
  3044                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  3045                              <1> 	;
  3046                              <1> 	; ((AX = R1)) input/output
  3047                              <1> 	; ((BX = R5)) output
  3048                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  3049                              <1> 	;    zf=1 -> block already in a I/O buffer
  3050                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  3051                              <1> 	;    ((DL = Device ID))
  3052                              <1> 	;    (((DH = 0 or 1)))
  3053                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  3054                              <1> 	;    ((CX and DH will not be used after return)))
  3055                              <1> 
  3056                              <1> 	; 14/07/2022
  3057                              <1> 	;	Modified registers: EBX, ECX, EDX, ESI, EDI
  3058                              <1> 
  3059                              <1> 	;;push 	esi ; ***
  3060                              <1> 		; mov r2,-(sp) / save r2 on stack
  3061                              <1>        		; mov $340,*$ps / set processor priority to 7
  3062                              <1> 		; 20/07/2013
  3063                              <1> 	; 26/04/2013
  3064                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  3065                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  3066                              <1> 	;add	edi, ebx
  3067                              <1> 	; 09/01/2022
  3068 00005590 0FB63D[F4650000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  3069 00005597 81C7[F6650000]      <1> 	add	edi, rdev
  3070                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  3071                              <1> 			;; EDI points to device id.
  3072 0000559D 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  3073                              <1> 	; 11/06/2015
  3074 000055A0 80BB[8E5D0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  3075 000055A7 720F                <1> 	jb	short bufaloc_9
  3076 000055A9 C705[5F660000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3076 000055B1 0000                <1>
  3077 000055B3 E94FDCFFFF          <1> 	jmp	error
  3078                              <1> bufaloc_9:
  3079 000055B8 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  3080                              <1> bufaloc_10: ; 02/07/2015
  3081                              <1> 	; 14/07/2022
  3082                              <1> 	;xor 	ebp, ebp ; 0
  3083                              <1> 	;push	ebp ; 0
  3084                              <1>         ;mov	ebp, esp	
  3085 000055BA 31FF                <1> 	xor	edi, edi ; 0	
  3086 000055BC 57                  <1> 	push	edi
  3087                              <1> bufaloc_1: ;1:
  3088                              <1> 		; clr -(sp) / vacant buffer
  3089 000055BD BE[C8650000]        <1>         mov 	esi, bufp
  3090                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3091                              <1> 			     ; / entrys in buffer area
  3092                              <1> bufaloc_2: ;2:
  3093 000055C2 8B1E                <1> 	mov	ebx, [esi]
  3094                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3095                              <1> 			    ; queue entry into r5
  3096                              <1> 	; 14/07/2022
  3097 000055C4 8B0B                <1> 	mov	ecx, [ebx]	
  3098                              <1> 	;test	word [ebx], 0F600h
  3099                              <1> 	; 15/07/2022
  3100 000055C6 F6C501              <1> 	test	ch, 1 ; valid buffer (content) ?
  3101                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3102 000055C9 7505                <1>         jnz	short bufaloc_3 ; yes
  3103                              <1> 		; bne 3f / branch when 
  3104                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3105                              <1>                        ; / (i.e., buffer busy)
  3106                              <1> 	;mov    [ebp], esi ; pointer to I/0 queue entry
  3107                              <1> 	; 14/07/2022
  3108                              <1> 	; save free buffer pointer 
  3109 000055CB 893424              <1> 	mov	[esp], esi
  3110                              <1>                 ; mov r2,(sp) ;/ save pointer to last non-busy buffer
  3111                              <1> 			; / found points to word 2 of I/O queue entry)
  3112                              <1> 	; continue to see if requested sector/block buffer
  3113                              <1> 	;	already is one of existing (valid) buffers
  3114                              <1> 	;jmp	short bufaloc_4
  3115 000055CE EB0E                <1> 	jmp	short bufaloc_11 ; 14/07/2022
  3116                              <1> bufaloc_3: ;3:
  3117                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3118                              <1> 	;
  3119 000055D0 38D1                <1> 	cmp	cl, dl ; 14/07/2022
  3120                              <1> 	;cmp	[ebx], dl	
  3121                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3122                              <1> 			       ; / as current device
  3123 000055D2 7508                <1> 	jne	short bufaloc_4
  3124                              <1>        		; bne 3f
  3125 000055D4 394304              <1> 	cmp	[ebx+4], eax
  3126                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3127                              <1> 			     ; / same as current block number
  3128 000055D7 7503                <1>        	jne	short bufaloc_4
  3129                              <1> 		; bne 3f
  3130                              <1> 	;add	esp, 4
  3131 000055D9 59                  <1> 	pop	ecx
  3132                              <1>        		; tst (sp)+ / bump stack pointer
  3133 000055DA EB1D                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3134                              <1> 				; jump to bufaloc_6 in original Unix v1
  3135                              <1>        		; br 1f / use this buffer
  3136                              <1> bufaloc_4: ;3:
  3137                              <1> 	; 14/07/2022
  3138                              <1> 	; save last valid buffer 
  3139                              <1> 	; (will be used if there is not a free buffer)
  3140 000055DC 89F7                <1> 	mov	edi, esi	
  3141                              <1> bufaloc_11:
  3142 000055DE 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3143                              <1> 	;
  3144 000055E1 81FE[E8650000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3145                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3146 000055E7 72D9                <1> 	jb	short bufaloc_2
  3147                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3148                              <1>                        ; / buffers not checked)
  3149 000055E9 5E                  <1>         pop	esi
  3150                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3151                              <1> 			     ; / to last free block
  3152 000055EA 09F6                <1>        	or	esi, esi 
  3153 000055EC 7502                <1> 	jnz	short bufaloc_5
  3154                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3155                              <1> 	        ; / if a free buffer is found branch to 2f
  3156                              <1> 	
  3157                              <1> 	; 14/07/2022        
  3158                              <1> 	; if there is not a free buffer
  3159                              <1> 	; we can use last valid buffer (the oldest buffer)
  3160                              <1> 	; ((ptr to new buffer is located at head of buff ptr chain))
  3161 000055EE 89FE                <1> 	mov	esi, edi
  3162                              <1> 
  3163                              <1> 	;;mov  ecx, [s.wait_]
  3164                              <1> 	;call	idle
  3165                              <1> 	;	; jsr r0,idle; s.wait+2 / idle if no free buffers
  3166                              <1> 	;jmp 	short bufaloc_10 ; 02/07/2015
  3167                              <1>        	;	; br 1b
  3168                              <1> bufaloc_5: ;2:
  3169                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3170                              <1> 	; 14/07/2022
  3171                              <1> 	;inc	dh ; Retro UNIX 8086 v1 modification
  3172                              <1> bufaloc_6: ;1:
  3173 000055F0 8B1E                <1>         mov    	ebx, [esi] 
  3174                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3175                              <1> 			     ; / entry in r5
  3176                              <1> 	;; 26/04/2013
  3177                              <1>         ;;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3178                              <1> 	;mov 	[ebx], dl
  3179                              <1> 		; movb cdev,(r5) / put current device number 
  3180                              <1> 				 ; / in I/O queue entry
  3181                              <1> 	; 14/07/2022
  3182                              <1> 	; invalidate buffer before r/w (new) disk sector/block
  3183                              <1> 	;mov	[ebx+1], dh ; 0
  3184                              <1> 	; 14/07/2022
  3185 000055F2 8913                <1> 	mov	[ebx], edx  ; dh = 0
  3186                              <1> 	
  3187 000055F4 894304              <1> 	mov 	[ebx+4], eax
  3188                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3189                              <1> 			     ; / of I/O queue entry
  3190                              <1> 	; 14/07/2022
  3191 000055F7 FEC6                <1> 	inc	dh ; dh = 1
  3192                              <1> bufaloc_7: ;1:
  3193 000055F9 81FE[C8650000]      <1>         cmp	esi, bufp
  3194                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3195                              <1> 			     ; / and put latest assigned
  3196 000055FF 760B                <1> 	jna	short bufaloc_8	
  3197                              <1>        		; blos 1f / buffer on the top 
  3198                              <1> 			; / (this makes if the lowest priority)
  3199                              <1> 	; 14/07/2022
  3200 00005601 89F7                <1> 	mov	edi, esi
  3201 00005603 83EE04              <1> 	sub	esi, 4
  3202 00005606 8B0E                <1> 	mov	ecx, [esi]
  3203 00005608 890F                <1> 	mov	[edi], ecx ; 14/07/2022
  3204                              <1> 	;mov	[esi+4], ecx
  3205                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3206 0000560A EBED                <1> 	jmp 	short bufaloc_7        
  3207                              <1> 		; br 1b
  3208                              <1> bufaloc_8: ;1:
  3209 0000560C 891E                <1>         mov	[esi], ebx
  3210                              <1> 		; mov r5,(r2)
  3211                              <1> 	;;pop	esi ; ***
  3212                              <1>        		; mov (sp)+,r2 / restore r2
  3213 0000560E 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3214                              <1> 		; Retro UNIX 8086 v1 modification
  3215                              <1> 		; zf=1 --> block already is in an I/O buffer
  3216                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3217 00005610 C3                  <1> 	retn
  3218                              <1> 		; rts r0
  3219                              <1> 
  3220                              <1> diskio:
  3221                              <1> 	; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21)
  3222                              <1> 	; ((Ref: Retro UNIX 386 v1.1 'diskio' modification: 12/07/2022))
  3223                              <1> 	; 
  3224                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3225                              <1> 	;	((simplified and shortened 'diskio.s' code)
  3226                              <1> 	;
  3227                              <1> 	; 12/02/2022
  3228                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  3229                              <1> 	; 10/07/2015
  3230                              <1> 	; 02/07/2015
  3231                              <1> 	; 16/06/2015
  3232                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3233                              <1> 	;	     (80386 protected mode modifications)	
  3234                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3235                              <1> 	;
  3236                              <1> 	; Retro UNIX 8086 v1 feature only !
  3237                              <1> 	;
  3238                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3239                              <1> 	; 04/07/2009 - 20/07/2011
  3240                              <1> 	;
  3241                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3242                              <1> 	;
  3243                              <1>         ; INPUTS ->
  3244                              <1> 	; 	   EBX = System I/O Buffer header address
  3245                              <1> 	;
  3246                              <1>         ; OUTPUTS -> cf=0 --> done 
  3247                              <1> 	; 	     cf=1 --> error code in AH
  3248                              <1> 	;
  3249                              <1> 	; (Modified registers: EAX, ECX, EDX)
  3250                              <1> 	
  3251                              <1> ;rw_disk_sector:
  3252                              <1> 	; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21)
  3253                              <1> 	; 12/02/2022
  3254                              <1> 	; 10/07/2015
  3255                              <1> 	; 02/07/2015
  3256                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3257                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3258                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3259                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3260                              <1> 	;
  3261                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3262                              <1> 	;mov	dh, 2
  3263                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3264 00005611 B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3265 00005613 668B03              <1> 	mov	ax, [ebx]
  3266                              <1> 	;
  3267 00005616 56                  <1> 	push	esi ; ****
  3268 00005617 53                  <1> 	push	ebx ; ***
  3269                              <1> 	;
  3270 00005618 0FB6C8              <1> 	movzx	ecx, al
  3271 0000561B 89CE                <1> 	mov	esi, ecx
  3272                              <1> 	;
  3273 0000561D 38F1                <1> 	cmp	cl, dh ; 2
  3274 0000561F 7202                <1> 	jb	short rwdsk0
  3275 00005621 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3276                              <1> rwdsk0:
  3277                              <1> 	; 12/07/2022
  3278                              <1> 	;mov	[drv], al
  3279 00005623 81C6[8E5D0000]      <1> 	add	esi, drv.status
  3280                              <1> 	; 11/06/2015
  3281 00005629 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3282 0000562C 7204                <1> 	jb      short rwdsk1
  3283                              <1> 	; 'drive not ready' error
  3284                              <1> 	; 12/02/2022
  3285                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3286                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3287                              <1> 	;;jmp	error
  3288                              <1> 	;stc	; cf = 1
  3289                              <1> 	;retn
  3290                              <1> 	; 12/02/2022
  3291 0000562E B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3292 00005630 EB1F                <1> 	jmp	short rwdsk_err1
  3293                              <1> rwdsk1:
  3294                              <1> 	;test	ah, 2
  3295                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3296                              <1> 	;		 ; write bit
  3297                              <1> 	;jz	short rwdsk2
  3298                              <1> 	
  3299                              <1> 	;;test	ah, 4
  3300                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3301                              <1> 	;;		 ; read bit
  3302                              <1> 	;;jz	short diskio_ret
  3303                              <1> 
  3304                              <1> 	;inc	dh ; 03h = write
  3305                              <1> 
  3306                              <1> 	; 08/07/2022
  3307 00005632 84F4                <1> 	test	ah, dh ; test ah, 2
  3308 00005634 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3309 00005636 FECE                <1> 	dec	dh
  3310                              <1> 		; dh = 01h = read
  3311                              <1> rwdsk2:
  3312 00005638 88C2                <1> 	mov	dl, al
  3313 0000563A 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3314 0000563D 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3315 0000563F C0E102              <1> 	shl	cl, 2
  3316 00005642 81C1[725D0000]      <1> 	add	ecx, drv.size ; disk size
  3317 00005648 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3318 0000564A 7214                <1> 	jb      short rwdsk3
  3319                              <1>  	; 'out of volume' error
  3320                              <1> 	; 12/02/2022
  3321                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3322                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3323                              <1> 	;;jmp	error
  3324                              <1> 	;stc	; cf = 1
  3325                              <1> 	;retn
  3326                              <1> 	; 12/02/2022
  3327 0000564C B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3328                              <1> rwdsk_err1:
  3329 00005651 C605[72660000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3330 00005658 890D[5F660000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3331 0000565E EB27                <1> 	jmp	short rwdsk_err2
  3332                              <1> rwdsk3:
  3333                              <1> 	; 11/06/2015
  3334 00005660 83C304              <1> 	add	ebx, 4 ; buffer address
  3335 00005663 C605[8E660000]04    <1> 	mov	byte [retry_count], 4
  3336                              <1> 	; 12/07/2022
  3337                              <1> 	;test	byte [esi], 1 ; LBA ready ?
  3338                              <1>         ;jz	short rwdsk_chs
  3339                              <1> rwdsk_lba:
  3340                              <1> 	; LBA read/write (with private LBA function) 
  3341                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3342 0000566A 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3343 0000566D 89C1                <1> 	mov	ecx, eax ; sector number
  3344                              <1> 	; ebx = buffer (data) address
  3345                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3346                              <1> rwdsk_lba_retry:
  3347                              <1> 	;mov	dl, [drv]
  3348                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3349                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3350                              <1> 	;;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3351                              <1> 	;mov	ah, 2 ; LBA write function number - 2
  3352                              <1> 	;add	ah, dh		
  3353                              <1> 	;mov	al, 1
  3354                              <1> 	;int	13h
  3355                              <1> 	;call	int13h
  3356                              <1> 	; 12/07/2022
  3357 0000566F 88F0                <1> 	mov	al, dh	; function (1 or 2)
  3358                              <1> 			; (1 = read, 2 = write )
  3359                              <1> 	; ecx = disk sector address (LBA)
  3360                              <1> 	; ebx = buffer address
  3361                              <1> 	;  dl = (physical) disk number
  3362                              <1> 	;  al = function (r/w)
  3363 00005671 E816CAFFFF          <1> 	call	DISK_IO
  3364                              <1> 
  3365 00005676 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3366 00005678 730E                <1> 	jnc	short rwdsk_lba_ok
  3367 0000567A 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3368 0000567D 7408                <1>         je      short rwdsk_lba_fails
  3369 0000567F FE0D[8E660000]      <1> 	dec	byte [retry_count]
  3370 00005685 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3371                              <1> rwdsk_err2:	; 12/02/2022
  3372                              <1> rwdsk_lba_fails:
  3373 00005687 F9                  <1> 	stc
  3374                              <1> rwdsk_lba_ok:
  3375 00005688 5B                  <1> 	pop	ebx ; ***
  3376 00005689 5E                  <1> 	pop	esi ; ****
  3377 0000568A C3                  <1> 	retn
  3378                              <1> rwdsk_lba_reset:
  3379                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3380                              <1> 	;int	13h
  3381                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3382                              <1> 	;mov	ah, 5 ; Alternate reset	 
  3383                              <1> 	;call	int13h
  3384                              <1> 	;jnc	short rwdsk_lba_retry
  3385                              <1> 	; 12/07/2022
  3386 0000568B 30C0                <1> 	xor	al, al ; 0 ; reset
  3387 0000568D E8FAC9FFFF          <1> 	call	DISK_IO
  3388 00005692 73DB                <1> 	jnc	short rwdsk_lba_retry
  3389                              <1> 
  3390 00005694 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3391 00005696 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3392                              <1> 
  3393                              <1> 	; 12/07/2022 
  3394                              <1> 	;	(CHS Read/Write setup is not needed here.)
  3395                              <1> 	; 	(LBA address will be converted to CHS parameters
  3396                              <1> 	;	in 'DISK_IO' procedure when/if it is required.)
  3397                              <1> 	
  3398                              <1> ;	; CHS read (convert LBA address to CHS values)	
  3399                              <1> ;rwdsk_chs:
  3400                              <1> ;	; 10/07/2015
  3401                              <1> ;	sub	esi, drv.status
  3402                              <1> ;	mov	ecx, esi
  3403                              <1> ;	add 	esi, drv.error
  3404                              <1> ;	; 02/07/2015
  3405                              <1> ;	; 16/06/2015
  3406                              <1> ;	; 11/06/2015 
  3407                              <1> ;	push	ebx ; ** ; buffer
  3408                              <1> ;	shl	ecx, 1
  3409                              <1> ;	push	ecx ; * 
  3410                              <1> ;	;
  3411                              <1> ;	mov	ebx, ecx
  3412                              <1> ;	mov	[rwdsk], dh ; 02/07/2015
  3413                              <1> ;	xor	edx, edx ; 0
  3414                              <1> ;	; 04/02/2022
  3415                              <1> ;	;sub	ecx, ecx 
  3416                              <1> ;	add     ebx, drv.spt
  3417                              <1> ;	mov	cx, [ebx] ; sector per track
  3418                              <1> ;		; EDX:EAX = LBA
  3419                              <1> ;	div	ecx
  3420                              <1> ;	mov	cl, dl	; sector number - 1
  3421                              <1> ;	inc	cl	; sector number (1 based)
  3422                              <1> ;	pop	ebx ; * ; 11/06/2015
  3423                              <1> ;	;push	cx
  3424                              <1> ;	; 04/02/2022
  3425                              <1> ;	push	ecx
  3426                              <1> ;	add     ebx, drv.heads
  3427                              <1> ;	mov	cx, [ebx] ; heads
  3428                              <1> ;	xor	edx, edx
  3429                              <1> ;		; EAX = cylinders * heads + head
  3430                              <1> ;	div	ecx
  3431                              <1> ;	;pop	cx     ; sector number
  3432                              <1> ;	; 04/02/2022
  3433                              <1> ;	pop	ecx
  3434                              <1> ;	mov	dh, dl ; head number
  3435                              <1> ;	mov	dl, [drv]
  3436                              <1> ;	mov	ch, al ; cylinder (bits 0-7)
  3437                              <1> ;	shl	ah, 6
  3438                              <1> ;	or	cl, ah ; cylinder (bits 8-9)
  3439                              <1> ;		       ; sector (bits 0-7)
  3440                              <1> ;	pop	ebx ; ** ; buffer ; 11/06/2015
  3441                              <1> ;		; CL = sector (bits 0-5)
  3442                              <1> ;		;      cylinder (bits 8-9 -> bits 6-7)
  3443                              <1> ;		; CH = cylinder (bits 0-7)
  3444                              <1> ;		; DH = head
  3445                              <1> ;		; DL = drive
  3446                              <1> ;	;
  3447                              <1> ;	mov	byte [retry_count], 4
  3448                              <1> ;rwdsk_retry:	
  3449                              <1> ;	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3450                              <1> ;	; 08/07/2022
  3451                              <1> ;	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3452                              <1> ;	mov	al, 1 ; sector count	
  3453                              <1> ;	;int	13h
  3454                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3455                              <1> ;	call	int13h
  3456                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3457                              <1> ;	jnc	short rwdsk_ok ; ah = 0
  3458                              <1> ;	cmp	ah, 80h ; time out ?
  3459                              <1> ;	je	short rwdsk_fails
  3460                              <1> ;	dec	byte [retry_count]
  3461                              <1> ;	jnz	short rwdsk_reset
  3462                              <1> ;rwdsk_fails:
  3463                              <1> ;	stc
  3464                              <1> ;rwdsk_ok:
  3465                              <1> ;	pop	ebx ; ***
  3466                              <1> ;	pop	esi ; ****
  3467                              <1> ;	retn
  3468                              <1> ;rwdsk_reset:
  3469                              <1> ;	; 02/02/2015
  3470                              <1> ;	sub	ah, ah
  3471                              <1> ;	cmp	dl, 80h
  3472                              <1> ;	jb	short rwdsk_fd_reset
  3473                              <1> ;	;mov	ah, 0Dh ; Alternate reset
  3474                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3475                              <1> ;	mov	ah, 5  ; Alternate reset
  3476                              <1> ;rwdsk_fd_reset:
  3477                              <1> ;	;int	13h
  3478                              <1> ;	call	int13h
  3479                              <1> ;	jnc	short rwdsk_retry
  3480                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3481                              <1> ;	jmp 	short rwdsk_ok
  3482                              <1> 
  3483                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3484                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3485                              <1> ;
  3486                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3487                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3488                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3489                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3490                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3491                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3492                              <1> ; as in original unix v1.
  3493                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3494                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3495                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3496                              <1> ;
  3497                              <1> ; Erdogan tan (10/07/2015) 
  3498                              <1> 
  3499                              <1> ;drum: / interrupt handler
  3500                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3501                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3502                              <1> ;                                      / error
  3503                              <1> ;               br 3f / no, error
  3504                              <1> ;       br      2f / error
  3505                              <1> ;
  3506                              <1> ;disk:
  3507                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3508                              <1> ;       jmp     *$0f
  3509                              <1> ;0:
  3510                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3511                              <1> ;      	        br 3f / no, errors
  3512                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3513                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3514                              <1> ;                        / to 1f
  3515                              <1> ;       br      4f
  3516                              <1> ;1:
  3517                              <1> ;       bit     $20000,rkcs
  3518                              <1> ;       beq     4f / wait for seek complete
  3519                              <1> ;       mov     $0b,0b-2
  3520                              <1> ;       mov     rkap,r1
  3521                              <1> ;2:
  3522                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3523                              <1> ;                          / the disk buffer
  3524                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3525                              <1> ;       inc     r1
  3526                              <1> ;       asr     (r1)
  3527                              <1> ;       asr     (r1)
  3528                              <1> ;       asr     (r1) / reissue request
  3529                              <1> ;       dec     r1
  3530                              <1> ;3:
  3531                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3532                              <1> ;       mov     ac,-(sp)
  3533                              <1> ;       mov     mq,-(sp) / put these on the stack
  3534                              <1> ;       mov     sc,-(sp)
  3535                              <1> ;       jsr     r0,poke
  3536                              <1> ;       mov     (sp)+,sc
  3537                              <1> ;       mov     (sp)+,mq / pop them off stack
  3538                              <1> ;       mov     (sp)+,ac
  3539                              <1> ;4:
  3540                              <1> ;       jmp     retisp / u4-3
  3541                              <1> ;
  3542                              <1> ;trapt:                  / r2 points to the
  3543                              <1> ;       mov     (r0)+,r2 / device control register
  3544                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3545                              <1> ;       tst     (sp)+
  3546                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3547                              <1> ;       bge     4b / device still active so branch
  3548                              <1> ;       bit     (r0),active / was device busy?
  3549                              <1> ;       beq     4b / no, stray interrupt
  3550                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3551                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3552                              <1> ;       bge     2f / if no error jump to 2f
  3553                              <1> ;       tst     (r0)+ / skip on error
  3554                              <1> ; 2:
  3555                              <1> ;       jmp     (r0)
  2058                                  %include 'u9.s'        ; 29/06/2015
  2059                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS9.INC
  2060                              <1> ; Last Modification: 13/06/2022
  2061                              <1> ; ----------------------------------------------------------------------------
  2062                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2063                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2064                              <1> ;
  2065                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2066                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2067                              <1> ; <Bell Laboratories (17/3/1972)>
  2068                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2069                              <1> ;
  2070                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2071                              <1> ;
  2072                              <1> ; ****************************************************************************
  2073                              <1> ; 21/11/2015
  2074                              <1> 
  2075                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) - Printer BIOS (Functions)
  2076                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2077                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2078                              <1> 
  2079                              <1> getch:
  2080                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2081                              <1> 	; 30/06/2015
  2082                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2083 00005698 28C0                <1> 	sub	al, al ; 0
  2084                              <1> getch_q: ; 06/08/2015
  2085 0000569A 8A25[76620000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2086 000056A0 EB06                <1>         jmp     short getc_n
  2087                              <1> 
  2088                              <1> getc: 
  2089                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2090                              <1> 	; 12/11/2015
  2091                              <1> 	; 15/09/2015
  2092                              <1> 	; 01/07/2015
  2093                              <1> 	; 30/06/2015
  2094                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2095                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2096                              <1> 	;
  2097                              <1> 	; Retro UNIX 8086 v1 modification !
  2098                              <1> 	; 
  2099                              <1> 	; 'getc' gets (next) character 
  2100                              <1> 	;	 from requested TTY (keyboard) buffer 
  2101                              <1> 	; INPUTS ->
  2102                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2103                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2104                              <1> 	;	(Keyboard buffer will point to 
  2105                              <1> 	;			next character at next call)
  2106                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2107                              <1> 	;	(Keyboard buffer will point to 
  2108                              <1> 	;			current character at next call)
  2109                              <1> 	; OUTPUTS ->
  2110                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2111                              <1> 	;     			 ZF=0 -> AX has (current) character
  2112                              <1> 	;      AL = ascii code
  2113                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2114                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2115                              <1> 	; Original UNIX V1 'getc': 
  2116                              <1> 	;		get a character off character list
  2117                              <1> 	;
  2118                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2119                              <1> 	;
  2120                              <1> 	; 30/06/2015 (32 bit modifications)
  2121                              <1> 	; 16/07/2013
  2122                              <1> 	; mov 	[getctty], ah
  2123                              <1> 	;
  2124                              <1> 
  2125 000056A2 8A25[5E660000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2126                              <1> getc_n:
  2127                              <1> 	; 30/06/2015
  2128 000056A8 08E4                <1> 	or	ah, ah
  2129 000056AA 740D                <1> 	jz	short getc0 
  2130 000056AC D0E4                <1> 	shl	ah, 1
  2131 000056AE 0FB6DC              <1> 	movzx	ebx, ah
  2132 000056B1 81C3[78620000]      <1> 	add	ebx, ttychr
  2133 000056B7 EB05                <1> 	jmp	short getc1
  2134                              <1> getc0:
  2135 000056B9 BB[78620000]        <1> 	mov	ebx, ttychr
  2136                              <1> getc1:
  2137 000056BE 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2138                              <1> 				; (by kb_int)	
  2139 000056C1 6609C9              <1> 	or	cx, cx
  2140 000056C4 7507                <1> 	jnz	short getc2
  2141 000056C6 20C0                <1> 	and 	al, al
  2142 000056C8 7415                <1> 	jz	short getc_s
  2143                              <1> 	;xor	ax, ax
  2144                              <1> 	; 24/12/2021
  2145 000056CA 31C0                <1> 	xor	eax, eax
  2146 000056CC C3                  <1> 	retn
  2147                              <1> getc2:	
  2148 000056CD 20C0                <1> 	and	al, al
  2149 000056CF 6689C8              <1> 	mov	ax, cx
  2150 000056D2 66B90000            <1> 	mov	cx, 0
  2151 000056D6 7506                <1> 	jnz	short getc3
  2152                              <1> getc_sn:
  2153 000056D8 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2154 000056DB 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2155                              <1> getc3:
  2156 000056DE C3                  <1> 	retn
  2157                              <1> getc_s:
  2158                              <1> 	; 12/11/2015
  2159                              <1> 	; 15/09/2015
  2160                              <1> 	; 01/07/2015
  2161                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2162                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2163                              <1> 	;
  2164                              <1> 	; tty  of the current process is not 
  2165                              <1> 	; current tty (ptty); so, current process only 
  2166                              <1> 	; can use keyboard input when its tty becomes 
  2167                              <1> 	; current tty (ptty).
  2168                              <1> 	; 'sleep' is for preventing an endless lock
  2169                              <1> 	; during this tty input request.
  2170                              <1> 	; (Because, the user is not looking at the video page
  2171                              <1> 	; of the process to undersand there is a keyboard
  2172                              <1> 	; input request.)
  2173                              <1> 	;
  2174                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2175                              <1> 	;
  2176                              <1> 	; 05/10/2013
  2177                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2178                              <1> 	;
  2179                              <1> 	; 10/10/2013
  2180                              <1> gcw0:
  2181 000056DF B10A                <1> 	mov	cl, 10 ; ch = 0
  2182                              <1> gcw1:	
  2183                              <1> 	; 12/11/2015
  2184 000056E1 E825DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2185                              <1> 	; 10/10/2013
  2186 000056E6 E8C4EFFFFF          <1> 	call	idle
  2187 000056EB 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2188                              <1> 				; (by kb_int)
  2189 000056EE 6609C0              <1> 	or	ax, ax
  2190                              <1> ;	jnz	short gcw3
  2191 000056F1 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2192                              <1> 	; 30/06/2015
  2193 000056F3 FEC9                <1> 	dec	cl
  2194 000056F5 75EA                <1> 	jnz	short gcw1
  2195                              <1> 	;
  2196 000056F7 8A25[5E660000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2197                              <1> ;	; 10/12/2013
  2198                              <1> ;	cmp 	ah, [ptty]
  2199                              <1> ;	jne	short gcw2
  2200                              <1> ;	; 14/02/2014
  2201                              <1> ;	cmp	byte [u.uno], 1
  2202                              <1> ;	jna	short gcw0		
  2203                              <1> ;gcw2:
  2204 000056FD E83AF0FFFF          <1> 	call	sleep
  2205                              <1> 	;
  2206                              <1> 	; 20/09/2013
  2207 00005702 8A25[5E660000]      <1> 	mov	ah, [u.ttyn]
  2208 00005708 30C0                <1> 	xor 	al, al
  2209 0000570A EB9C                <1> 	jmp	short getc_n
  2210                              <1> ;gcw3:
  2211                              <1> gcw2: 	; 15/09/2015
  2212                              <1> 	; 10/10/2013
  2213 0000570C 30C9                <1> 	xor	cl, cl
  2214 0000570E EBC8                <1> 	jmp	short getc_sn
  2215                              <1> 
  2216                              <1> putc:	
  2217                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2218                              <1> 	; 13/08/2015
  2219                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2220                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2221                              <1> 	;
  2222                              <1> 	; Retro UNIX 8086 v1 modification !
  2223                              <1> 	; 
  2224                              <1> 	; 'putc' puts a character 
  2225                              <1> 	;	 onto requested (tty) video page or
  2226                              <1> 	;	 serial port
  2227                              <1> 	; INPUTS ->
  2228                              <1> 	;     AL = ascii code of the character
  2229                              <1> 	;     AH = video page (tty) number (0 to 7)
  2230                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2231                              <1> 	; OUTPUTS ->
  2232                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2233                              <1> 	;      			ZF=0 -> AX has (current) character
  2234                              <1> 	;     cf=0 and AH = 0 -> no error
  2235                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2236                              <1> 	; 
  2237                              <1> 	; Original UNIX V1 'putc': 
  2238                              <1> 	;     put a character at the end of character list
  2239                              <1> 	;
  2240                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2241                              <1> 	;
  2242 00005710 80FC07              <1> 	cmp	ah, 7
  2243                              <1>         ;ja	sndc
  2244 00005713 770A                <1>         ja      short sndc ; 24/12/2024
  2245                              <1> 	; 30/06/2015
  2246 00005715 0FB6DC              <1> 	movzx	ebx, ah
  2247                              <1> 	; 13/08/2015
  2248 00005718 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2249 0000571A E99DBCFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2250                              <1> 
  2251                              <1> sndc:   ; <Send character>
  2252                              <1> 	;
  2253                              <1> 	; 12/01/2022
  2254                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2255                              <1> 	; 17/11/2015
  2256                              <1> 	; 16/11/2015
  2257                              <1> 	; 11/11/2015
  2258                              <1> 	; 10/11/2015
  2259                              <1> 	; 09/11/2015
  2260                              <1> 	; 08/11/2015
  2261                              <1> 	; 07/11/2015
  2262                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2263                              <1> 	; 29/10/2015
  2264                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2265                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2266                              <1> 	;
  2267                              <1> 	; Retro UNIX 8086 v1 feature only !
  2268                              <1> 	;
  2269                              <1> 	; ah = [u.ttyn]
  2270                              <1> 	;
  2271                              <1> 	; 30/06/2015
  2272 0000571F 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2273                              <1> 	; 07/11/2015
  2274 00005722 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2275                              <1> sndc0:
  2276                              <1> 	; 07/11/2015
  2277 00005725 E860F0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2278 0000572A 7405                <1> 	jz	short sndc1
  2279 0000572C E8DADBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2280                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2281                              <1> sndc1:
  2282                              <1> 	; 16/11/2015
  2283                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2284                              <1> 	; 24/12/2021
  2285 00005731 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2286                              <1> sndcx:
  2287 00005733 8A83[BA620000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2288 00005739 8AA3[B8620000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2289                              <1> 	;
  2290                              <1> 	; 17/11/2015
  2291                              <1> 	; check 'request for response' status
  2292 0000573F 80BB[B4620000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2293 00005746 740A                <1> 	jz	short query
  2294                              <1> response:
  2295 00005748 FE05[B7620000]      <1> 	inc 	byte [comqr] ; query or response status
  2296 0000574E B0FF                <1> 	mov	al, 0FFh	 
  2297 00005750 EB14                <1> 	jmp	short sndc3
  2298                              <1> query:
  2299 00005752 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2300 00005754 750E                <1> 	jnz 	short sndc2 ; normal character
  2301                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2302                              <1> 	;je	short sndc2  ; yes, already responded
  2303                              <1> 	; 16/11/2015
  2304                              <1> 	; query: request for response (again)
  2305 00005756 8883[B8620000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2306 0000575C FE05[B7620000]      <1> 	inc 	byte [comqr] ; query or response status
  2307 00005762 EB02                <1> 	jmp	short sndc3
  2308                              <1> sndc2:
  2309 00005764 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2310                              <1> sndc3:
  2311 00005766 8883[BA620000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2312 0000576C 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2313                              <1> 	; 30/06/2015
  2314 0000576E E847D5FFFF          <1> 	call	sp_status ; get serial port status
  2315                              <1> 	; AL = Line status, AH = Modem status
  2316                              <1> 	; 07/11/2015
  2317 00005773 A880                <1> 	test	al, 80h
  2318 00005775 7504                <1> 	jnz	short sndc4
  2319 00005777 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2320 00005779 751A                <1> 	jnz	short sndc5
  2321                              <1> sndc4: 	; Check line status again
  2322                              <1> 	; 16/11/2015
  2323                              <1> 	;push	cx
  2324                              <1> 	; 24/12/2021
  2325 0000577B 51                  <1> 	push	ecx
  2326                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2327                              <1> 	; 12/01/2022
  2328 0000577C 31C9                <1> 	xor	ecx, ecx
  2329 0000577E B106                <1> 	mov	cl, 6
  2330 00005780 E82EBDFFFF          <1> 	call	WAITF
  2331                              <1> 	;pop	cx
  2332                              <1> 	; 24/12/1021
  2333 00005785 59                  <1> 	pop	ecx
  2334                              <1> 	;
  2335 00005786 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2336 00005788 E82DD5FFFF          <1> 	call	sp_status ; get serial port status
  2337                              <1> 	; 16/11/2015
  2338                              <1> 	; 09/11/2015
  2339                              <1> 	; 08/11/2015
  2340 0000578D A880                <1> 	test	al, 80h	; time out error
  2341 0000578F 7565                <1>         jnz     short sndc7
  2342 00005791 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2343 00005793 7461                <1>         jz	short sndc7
  2344                              <1> sndc5:  
  2345 00005795 8A83[BA620000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2346 0000579B 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2347 0000579F 28DE                <1> 	sub	dh, bl
  2348 000057A1 EE                  <1> 	out	dx, al	   ; send on serial port
  2349                              <1> 	; 10/11/2015
  2350                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2351                              <1> 	; (to improve text flow to the terminal)
  2352                              <1> 	; ('diskette.inc': 'WAITF')
  2353                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2354                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2355                              <1> 	;push	cx
  2356                              <1> 	; 24/12/2021
  2357 000057A2 51                  <1> 	push	ecx
  2358                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2359                              <1> 	; 12/01/2022
  2360 000057A3 29C9                <1> 	sub	ecx, ecx
  2361 000057A5 B106                <1> 	mov	cl, 6
  2362 000057A7 E807BDFFFF          <1> 	call	WAITF
  2363                              <1> 	;pop	cx
  2364                              <1> 	; 24/12/1021
  2365 000057AC 59                  <1> 	pop	ecx
  2366                              <1>     	;
  2367                              <1> 	; 07/11/2015
  2368 000057AD 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2369                              <1> 	;
  2370 000057AF E806D5FFFF          <1> 	call	sp_status ; get serial port status
  2371                              <1> 	; AL = Line status, AH = Modem status
  2372                              <1> 	;
  2373 000057B4 E8D1EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2374 000057B9 7405                <1> 	jz	short sndc6
  2375 000057BB E84BDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2376                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2377                              <1> sndc6:
  2378 000057C0 3C80                <1> 	cmp	al, 80h
  2379 000057C2 7332                <1> 	jnb	short sndc7		
  2380                              <1> 	;
  2381 000057C4 803D[B7620000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2382 000057CB 7244                <1> 	jb	short sndc8 	; no, normal character
  2383 000057CD 883D[B7620000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2384                              <1> 	; 17/11/2015
  2385 000057D3 E8D7EEFFFF          <1> 	call	idle
  2386                              <1> 	;
  2387 000057D8 38BB[BA620000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2388                              <1>         ;ja	sndc2       ; response (will be followed by
  2389                              <1> 			    ; a normal character)
  2390                              <1> 	; 24/12/2021
  2391 000057DE 7602                <1> 	jna	short sndc_10
  2392 000057E0 EB82                <1> 	jmp	sndc2
  2393                              <1> sndc_10:
  2394                              <1> 	; Query request must be responded by the terminal
  2395                              <1> 	; before sending a normal character !
  2396 000057E2 53                  <1> 	push	ebx
  2397                              <1> 	;push	cx ; *** cl = character (to be sent)
  2398                              <1> 	; 24/12/2021
  2399 000057E3 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2400 000057E4 8A25[5E660000]      <1> 	mov	ah, [u.ttyn]
  2401 000057EA E84DEFFFFF          <1> 	call	sleep ; this process will be awakened by
  2402                              <1> 		      ; received data available interrupt
  2403                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2404                              <1> 	; 24/12/2021
  2405 000057EF 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2406 000057F0 5B                  <1> 	pop	ebx
  2407 000057F1 E93DFFFFFF          <1>         jmp	sndcx
  2408                              <1> sndc7:
  2409                              <1> 	 ; 16/11/2015
  2410 000057F6 803D[B7620000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2411 000057FD 7213                <1> 	jb	short sndc9 	; no
  2412                              <1> 	;
  2413 000057FF 88BB[B8620000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2414 00005805 88BB[BA620000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2415                              <1> 	;
  2416 0000580B 883D[B7620000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2417                              <1> sndc8:
  2418 00005811 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2419                              <1> sndc9:
  2420                              <1> 	; AL = Line status, AH = Modem status
  2421 00005812 C3                  <1> 	retn
  2422                              <1> 
  2423                              <1> get_cpos:
  2424                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2425                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2426                              <1> 	;
  2427                              <1> 	; INPUT -> bl = video page number
  2428                              <1> 	; RETURN -> dx = cursor position
  2429                              <1> 
  2430 00005813 53                  <1> 	push	ebx
  2431 00005814 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2432 00005817 D0E3                <1> 	shl	bl, 1
  2433 00005819 81C3[66620000]      <1> 	add	ebx, cursor_posn
  2434 0000581F 668B13              <1> 	mov	dx, [ebx]
  2435 00005822 5B                  <1> 	pop	ebx
  2436 00005823 C3                  <1> 	retn
  2437                              <1> 
  2438                              <1> read_ac_current:
  2439                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2440                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2441                              <1> 	;
  2442                              <1> 	; INPUT -> bl = video page number
  2443                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2444                              <1> 
  2445 00005824 E8F9BCFFFF          <1> 	call 	find_position ; 'video.inc'
  2446                              <1> 	; dx = status port
  2447                              <1> 	; esi = cursor location/address
  2448 00005829 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2449 0000582F 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2450 00005832 C3                  <1> 	retn
  2451                              <1> 
  2452                              <1> syssleep:
  2453                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2454                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2455                              <1> 	;
  2456                              <1> 	; Retro UNIX 8086 v1 feature only
  2457                              <1> 	; (INPUT -> none)
  2458                              <1> 	;
  2459 00005833 0FB61D[59660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2460 0000583A 8AA3[63630000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2461 00005840 E8F7EEFFFF          <1> 	call	sleep
  2462 00005845 E9DDD9FFFF          <1> 	jmp	sysret
  2463                              <1> 
  2464                              <1> 	; 27/02/2022
  2465                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2466                              <1> %if 0
  2467                              <1> 
  2468                              <1> vp_clr:
  2469                              <1> 	; Reset/Clear Video Page
  2470                              <1> 	;
  2471                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2472                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2473                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2474                              <1> 	;
  2475                              <1> 	; Retro UNIX 8086 v1 feature only !
  2476                              <1> 	;
  2477                              <1> 	; INPUTS -> 
  2478                              <1> 	;   BL = video page number	 
  2479                              <1> 	;
  2480                              <1> 	; OUTPUT ->
  2481                              <1> 	;   none
  2482                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2483                              <1> 	;
  2484                              <1> 	; 04/12/2013
  2485                              <1> 	sub	al, al
  2486                              <1> 	; al = 0 (clear video page)
  2487                              <1> 	; bl = video page
  2488                              <1> 	mov	ah, 07h
  2489                              <1> 	; ah = 7 (attribute/color)
  2490                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2491                              <1> 	; 24/12/2021
  2492                              <1> 	xor	ecx, ecx
  2493                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2494                              <1> 	call	scroll_up
  2495                              <1> 	; bl = video page
  2496                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2497                              <1> 	; 24/12/2021
  2498                              <1> 	xor	edx, edx 
  2499                              <1> 	jmp 	set_cpos
  2500                              <1> 
  2501                              <1> %endif
  2502                              <1> 
  2503                              <1> sysmsg:
  2504                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2505                              <1> 	; 11/11/2015
  2506                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2507                              <1> 	; Print user-application message on user's console tty
  2508                              <1> 	;
  2509                              <1> 	; Input -> EBX = Message address
  2510                              <1> 	;	   ECX = Message length (max. 255)
  2511                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2512                              <1> 	;
  2513 0000584A 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2514                              <1> 	;ja	sysret ; nothing to do with big message size
  2515 00005850 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2516 00005852 08C9                <1> 	or	cl, cl
  2517                              <1> 	;jz	sysret
  2518 00005854 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2519 00005856 20D2                <1> 	and	dl, dl
  2520 00005858 7502                <1> 	jnz	short sysmsg0
  2521 0000585A B207                <1> 	mov	dl, 07h ; default color
  2522                              <1> 		; (black background, light gray character)
  2523                              <1> sysmsg0:
  2524 0000585C 891D[30660000]      <1> 	mov	[u.base], ebx
  2525 00005862 8815[77620000]      <1> 	mov	[ccolor], dl ; color attributes
  2526 00005868 89E5                <1> 	mov	ebp, esp
  2527 0000586A 31DB                <1> 	xor	ebx, ebx ; 0
  2528 0000586C 891D[38660000]      <1> 	mov	[u.nread], ebx ; 0
  2529                              <1> 	;
  2530 00005872 381D[71660000]      <1> 	cmp	[u.kcall], bl ; 0
  2531 00005878 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2532                              <1> 	;
  2533 0000587A 890D[34660000]      <1> 	mov	[u.count], ecx
  2534 00005880 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2535                              <1> 	; 24/12/2021
  2536                              <1> 	; (dword alignment for esp)
  2537 00005881 F6C103              <1> 	test	cl, 3
  2538 00005884 7404                <1> 	jz	short sysmsg_7
  2539 00005886 80C903              <1> 	or	cl, 3
  2540 00005889 41                  <1> 	inc	ecx
  2541                              <1> sysmsg_7:
  2542 0000588A 29CC                <1> 	sub	esp, ecx
  2543 0000588C 89E7                <1> 	mov	edi, esp
  2544 0000588E 89E6                <1> 	mov	esi, esp
  2545 00005890 66891D[6F660000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2546                              <1> 	; 11/11/2015
  2547 00005897 8A25[40660000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2548                              <1> 	; 0 = none
  2549 0000589D FECC                <1> 	dec	ah
  2550 0000589F 790C                <1> 	jns	short sysmsg1 
  2551 000058A1 8A1D[59660000]      <1> 	mov	bl, [u.uno] ; process number	
  2552 000058A7 8AA3[63630000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2553                              <1> sysmsg1:
  2554 000058AD 8825[5E660000]      <1> 	mov	[u.ttyn], ah
  2555                              <1> sysmsg2:
  2556 000058B3 E851F6FFFF          <1> 	call	cpass
  2557 000058B8 7416                <1> 	jz	short sysmsg5
  2558 000058BA AA                  <1> 	stosb
  2559 000058BB 20C0                <1> 	and	al, al
  2560 000058BD 75F4                <1> 	jnz	short sysmsg2
  2561                              <1> sysmsg3:
  2562 000058BF 80FC07              <1> 	cmp	ah, 7 ; tty number
  2563 000058C2 7711                <1> 	ja	short sysmsg6 ; serial port
  2564 000058C4 E83E000000          <1> 	call	print_cmsg
  2565                              <1> sysmsg4:
  2566 000058C9 89EC                <1> 	mov	esp, ebp	
  2567                              <1> sysmsg8: ; 24/12/2021	
  2568 000058CB E957D9FFFF          <1> 	jmp	sysret
  2569                              <1> sysmsg5:
  2570 000058D0 C60700              <1> 	mov	byte [edi], 0
  2571 000058D3 EBEA                <1> 	jmp	short sysmsg3
  2572                              <1> sysmsg6:
  2573 000058D5 8A06                <1> 	mov	al, [esi]
  2574 000058D7 E843FEFFFF          <1> 	call	sndc
  2575 000058DC 72EB                <1> 	jc	short sysmsg4
  2576 000058DE 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2577 000058E1 76E6                <1> 	jna	short sysmsg4
  2578 000058E3 46                  <1> 	inc 	esi
  2579 000058E4 8A25[5E660000]      <1> 	mov	ah, [u.ttyn]
  2580 000058EA EBE9                <1> 	jmp	short sysmsg6
  2581                              <1> 
  2582                              <1> sysmsgk: ; Temporary (01/07/2015)
  2583                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2584                              <1> 	; (ECX -character count- will not be considered)
  2585 000058EC 8B35[30660000]      <1> 	mov	esi, [u.base]
  2586 000058F2 8A25[76620000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2587 000058F8 8825[5E660000]      <1> 	mov	[u.ttyn], ah
  2588 000058FE C605[71660000]00    <1> 	mov	byte [u.kcall], 0
  2589 00005905 EBB8                <1> 	jmp	short sysmsg3
  2590                              <1> 	
  2591                              <1> print_cmsg: 
  2592                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2593                              <1> 	;
  2594                              <1> 	; print message (on user's console tty) 
  2595                              <1> 	;	with requested color
  2596                              <1> 	;
  2597                              <1> 	; INPUTS:
  2598                              <1> 	;	esi = message address
  2599                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2600                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2601                              <1> 	;
  2602 00005907 AC                  <1> 	lodsb
  2603                              <1> pcmsg1:
  2604 00005908 56                  <1> 	push 	esi
  2605 00005909 0FB61D[5E660000]    <1>         movzx   ebx, byte [u.ttyn]
  2606 00005910 8A25[77620000]      <1> 	mov	ah, [ccolor]
  2607 00005916 E8A1BAFFFF          <1> 	call 	write_tty
  2608 0000591B 5E                  <1> 	pop	esi
  2609 0000591C AC                  <1> 	lodsb
  2610 0000591D 20C0                <1> 	and 	al, al  ; 0
  2611 0000591F 75E7                <1> 	jnz 	short pcmsg1
  2612 00005921 C3                  <1> 	retn
  2613                              <1> 
  2614                              <1> sysgeterr:
  2615                              <1> 	; 16/02/2022
  2616                              <1> 	; 09/12/2015
  2617                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2618                              <1> 	; Get last error number or page fault count
  2619                              <1> 	; (for debugging)
  2620                              <1> 	;
  2621                              <1> 	; Input -> EBX = return type
  2622                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2623                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2624                              <1> 	;	   FFFFFFFEh = total page fault count
  2625                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2626                              <1> 	;
  2627                              <1> 	; Output -> EAX = last error number or page fault count
  2628                              <1> 	;	   (depending on EBX input)
  2629                              <1> 	; 	
  2630 00005922 21DB                <1> 	and 	ebx, ebx
  2631 00005924 750F                <1> 	jnz	short glerr_2
  2632                              <1> glerr_0:
  2633 00005926 A1[5F660000]        <1> 	mov	eax, [u.error]
  2634                              <1> glerr_1:
  2635 0000592B A3[10660000]        <1> 	mov	[u.r0], eax
  2636                              <1>  	;retn
  2637                              <1> 	; 16/02/2022 (BugFix)
  2638 00005930 E9F2D8FFFF          <1> 	jmp	sysret
  2639                              <1> glerr_2:
  2640 00005935 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2641 00005936 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2642 00005938 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2643 00005939 75EB                <1> 	jnz	short glerr_0
  2644 0000593B A1[FC620000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2645 00005940 EBE9                <1>         jmp     short glerr_1
  2646                              <1> glerr_3:
  2647 00005942 A1[73660000]        <1> 	mov 	eax, [u.pfcount]
  2648 00005947 EBE2                <1> 	jmp	short glerr_1
  2649                              <1> 
  2650                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2651                              <1> ;	     - PRINTER BIOS (Functions)		
  2652                              <1> 
  2653                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2654                              <1> ;
  2655                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2656                              <1> ; PRINTER_IO								       :
  2657                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2658                              <1> ; INPUT 								       :
  2659                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2660                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2661                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2662                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2663                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2664                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2665                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2666                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2667                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2668                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2669                              <1> ;		   |	   |	   |	   |	   |			       :
  2670                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2671                              <1> ;		   |	   |	   |	   |				       :
  2672                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2673                              <1> ;		   |	   |	   |					       :
  2674                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2675                              <1> ;		   |	   |						       :
  2676                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2677                              <1> ;		   |							       :
  2678                              <1> ;		   |_ 1 = NOT BUSY					       :
  2679                              <1> ;									       :
  2680                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2681                              <1> ;		IN @PRINTER_BASE AREA					       :
  2682                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2683                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2684                              <1> ;									       :
  2685                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2686                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2687                              <1> ;									       :
  2688                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2689                              <1> ;		ALL OTHERS UNCHANGED					       :
  2690                              <1> ;-------------------------------------------------------------------------------
  2691                              <1> 
  2692                              <1> int17h:
  2693                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2694                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2695                              <1> 	;
  2696                              <1> 	; (Default printer port: 378h) ; LPT1
  2697                              <1> 	; (Number of printers = 1)
  2698                              <1> 	
  2699                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2700                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2701                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2702                              <1> 
  2703                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2704                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2705                              <1> 
  2706                              <1> 	; INPUT:
  2707                              <1> 	;	ah = 0 -> print the character in AL 
  2708                              <1> 	;		 (sys write with write count >0)
  2709                              <1> 	;	ah = 1 -> initialize printer port
  2710                              <1> 	;		 (sys open)	
  2711                              <1> 	;	ah = 2 -> read the printer status 
  2712                              <1> 	;		 (sys write with write count = 0)
  2713                              <1> 	; OUTPUT:
  2714                              <1> 	;	ah = printer status
  2715                              <1> 
  2716                              <1> 	; Modified registers: eax, ecx, edx
  2717                              <1> 
  2718                              <1> PRINTER_IO_1:
  2719 00005949 08E4                <1> 	or	ah, ah
  2720 0000594B 7417                <1> 	jz	short _b20
  2721 0000594D FECC                <1> 	dec	ah
  2722 0000594F 7444                <1> 	jz	short _b80
  2723                              <1> 	;dec 	ah
  2724                              <1> 	;jz	short _b50
  2725                              <1> _b50:
  2726                              <1> 	;-----	PRINTER STATUS
  2727                              <1> B50:
  2728 00005951 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2729                              <1> B60:
  2730 00005952 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2731                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2732                              <1> 				; POINT TO CONTROL PORT
  2733 00005956 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2734 00005957 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2735 00005958 88C4                <1> 	mov	ah, al		; SAVE
  2736 0000595A 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2737                              <1> B70:
  2738 0000595D 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2739 0000595E 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2740 00005960 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2741                              <1> B10:
  2742 00005963 C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2743                              <1> _b20:
  2744                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2745 00005964 B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2746                              <1> B20:
  2747 00005969 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2748 0000596A 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2749 0000596E EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2750 0000596F FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2751                              <1> 
  2752                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2753                              <1> B25:
  2754                              <1> 	;-----	WAIT BUSY
  2755                              <1> B35:
  2756 00005971 EC                  <1> 	in	al, dx		; GET STATUS
  2757 00005972 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2758 00005974 A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2759 00005976 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2760 00005978 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2761 0000597D E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2762                              <1> 
  2763 0000597F 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2764 00005982 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2765 00005985 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2766                              <1> 
  2767                              <1> B40:				; SEND STROBE PULSE
  2768 00005987 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2769 00005989 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2770 0000598B FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2771 0000598C EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2772                              <1> 	; IODELAY
  2773                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2774                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2775                              <1> 	; NEWIODELAY
  2776 0000598D E6EB                <1> 	out	0EBh, al
  2777                              <1> 
  2778 0000598F B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2779 00005991 EE                  <1> 	out	dx, al
  2780 00005992 FB                  <1> 	sti			; INTERRUPTS BACK ON
  2781                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2782                              <1> 	;jmp	short B50
  2783 00005993 EBBD                <1> 	jmp	short B60
  2784                              <1> 
  2785                              <1> _b80:
  2786                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2787                              <1> B80:
  2788 00005995 50                  <1> 	push	eax		; SAVE (AL)
  2789 00005996 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2790 0000599A B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2791 0000599C EE                  <1> 	out	dx, al
  2792                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2793 0000599D B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2794                              <1> B90:				; INIT_LOOP
  2795                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2796                              <1> 	;jnz	short B90	; INIT_LOOP
  2797 000059A2 E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2798 000059A7 E2F9                <1> 	loop	B90	
  2799 000059A9 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2800 000059AB EE                  <1> 	out	dx, al
  2801 000059AC EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2802                              <1> 
  2803                              <1> 
  2804                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2805                              <1> ; -------------------------------------------------------------------
  2806                              <1> ;
  2807                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2808                              <1> ;;65536/30 = 2185
  2809                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2810                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2811                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2812                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2813                              <1> ;
  2814                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2815                              <1> ;
  2816                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2817                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2818                              <1> ;;1,080,000 / 30 = 36,000
  2819                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2820                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2821                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2822                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2823                              <1> ;
  2824                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2825                              <1> 
  2826                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2827                              <1> ; ------------------------------------------
  2828                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2829                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2830                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2831                              <1> ;	OUTPUT: BX:CX destroyed.
  2832                              <1> ;
  2833                              <1> ;	SAVES:	AX (except when NO STACK)
  2834                              <1> ;
  2835                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2836                              <1> ;		used this way, AX is assumed to be destroyed.
  2837                              <1> 
  2838                              <1> WAIT_REFRESH:
  2839                              <1> 	; 13/06/2022
  2840                              <1> 	; Modified for Retro UNIX 386 v1
  2841                              <1> 	
  2842                              <1> 	; (wait for 30 micro seconds)
  2843                              <1> 
  2844                              <1> 	SYS1	equ 61h ; PORT_B
  2845                              <1> 
  2846                              <1> WR_SHORT:
  2847 000059AE 50                  <1> 	push	eax
  2848                              <1> WR_STAT_0:
  2849 000059AF E461                <1> 	in	al, SYS1	; wait for high to low
  2850 000059B1 A810                <1> 	test	al, 10h		; transition on memory
  2851 000059B3 75FA                <1> 	jnz	short WR_STAT_0 
  2852                              <1> WR_STAT_1:
  2853 000059B5 E461                <1> 	in	al, SYS1
  2854 000059B7 A810                <1> 	test	al, 10h
  2855 000059B9 74FA                <1> 	jz	short WR_STAT_1
  2856 000059BB 58                  <1> 	pop	eax
  2857 000059BC C3                  <1> 	retn
  2059                                  
  2060                                  ; 07/03/2015
  2061                                  ; Temporary Code
  2062                                  display_disks:
  2063 000059BD 803D[6C5D0000]00        	cmp 	byte [fd0_type], 0
  2064 000059C4 7605                    	jna 	short ddsks1
  2065 000059C6 E87D000000              	call	pdskm
  2066                                  ddsks1:
  2067 000059CB 803D[6D5D0000]00        	cmp	byte [fd1_type], 0
  2068 000059D2 760C                    	jna	short ddsks2
  2069 000059D4 C605[315F0000]31        	mov	byte [dskx], '1'
  2070 000059DB E868000000              	call	pdskm
  2071                                  ddsks2:
  2072 000059E0 803D[6E5D0000]00        	cmp	byte [hd0_type], 0
  2073 000059E7 7654                    	jna	short ddsk6
  2074 000059E9 66C705[2F5F0000]68-     	mov	word [dsktype], 'hd'
  2074 000059F1 64                 
  2075 000059F2 C605[315F0000]30        	mov	byte [dskx], '0'
  2076 000059F9 E84A000000              	call	pdskm
  2077                                  ddsks3:
  2078 000059FE 803D[6F5D0000]00        	cmp	byte [hd1_type], 0
  2079 00005A05 7636                    	jna	short ddsk6
  2080 00005A07 C605[315F0000]31        	mov	byte [dskx], '1'
  2081 00005A0E E835000000              	call	pdskm
  2082                                  ddsks4:
  2083 00005A13 803D[705D0000]00        	cmp	byte [hd2_type], 0
  2084 00005A1A 7621                    	jna	short ddsk6
  2085 00005A1C C605[315F0000]32        	mov	byte [dskx], '2'
  2086 00005A23 E820000000              	call	pdskm
  2087                                  ddsks5:
  2088 00005A28 803D[715D0000]00        	cmp	byte [hd3_type], 0
  2089 00005A2F 760C                    	jna	short ddsk6
  2090 00005A31 C605[315F0000]33        	mov	byte [dskx], '3'
  2091 00005A38 E80B000000              	call	pdskm
  2092                                  ddsk6:
  2093 00005A3D BE[405F0000]            	mov	esi, nextline
  2094 00005A42 E806000000              	call	pdskml
  2095                                  pdskm_ok:
  2096 00005A47 C3                      	retn
  2097                                  pdskm:
  2098 00005A48 BE[2D5F0000]            	mov	esi, dsk_ready_msg
  2099                                  pdskml:	
  2100 00005A4D AC                      	lodsb
  2101 00005A4E 08C0                    	or	al, al
  2102 00005A50 74F5                    	jz	short pdskm_ok
  2103 00005A52 56                      	push	esi
  2104 00005A53 31DB                    	xor	ebx, ebx ; 0
  2105                                  			; Video page 0 (bl=0)
  2106 00005A55 B407                    	mov	ah, 07h ; Black background, 
  2107                                  			; light gray forecolor
  2108 00005A57 E860B9FFFF              	call	write_tty
  2109 00005A5C 5E                      	pop	esi
  2110 00005A5D EBEE                    	jmp	short pdskml
  2111                                  
  2112 00005A5F 90                      align 16
  2113                                  
  2114                                  gdt:	; Global Descriptor Table
  2115                                  	; (30/07/2015, conforming cs)
  2116                                  	; (26/03/2015)
  2117                                  	; (24/03/2015, tss)
  2118                                  	; (19/03/2015)
  2119                                  	; (29/12/2013)
  2120                                  	;
  2121 00005A60 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2122                                  	; 18/08/2014
  2123                                  			; 8h kernel code segment, base = 00000000h		
  2124 00005A68 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2125                                  			; 10h kernel data segment, base = 00000000h	
  2126 00005A70 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2127                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2128 00005A78 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2129                                  			; 23h user data segment, base address = 400000h ; CORE
  2130 00005A80 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2131                                  			; Task State Segment
  2132 00005A88 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2133                                  			       ;  no IO permission in ring 3)
  2134                                  gdt_tss0:
  2135 00005A8A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2136                                  gdt_tss1:
  2137 00005A8C 00                      	db 0  ; TSS base address, bits 16-23 
  2138                                  	      		; 49h	
  2139 00005A8D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2140 00005A8E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2141                                  gdt_tss2:
  2142 00005A8F 00                      	db 0  ; TSS base address, bits 24-31 
  2143                                  
  2144                                  gdt_end:
  2145                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2146                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2147                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2148                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2149                                  
  2150                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2151                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2152                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2153                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2154                                  		; W= Writeable, A= Accessed
  2155                                  	
  2156                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2157                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2158                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2159                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2160                                  
  2161                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2162                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2163                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2164                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2165                                  	
  2166                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2167                                  
  2168                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2169                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2170                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2171                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2172                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2173                                  		; AVL= Available to programmers	
  2174                                  
  2175                                  gdtd:
  2176 00005A90 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2177 00005A92 [605A0000]                      dd gdt			; Address of the GDT
  2178                                  
  2179                                  	; 20/08/2014
  2180                                  idtd:
  2181 00005A96 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2182 00005A98 [E05F0000]                      dd idt			; Address of the IDT
  2183                                  
  2184                                  Align 4
  2185                                  
  2186                                  	; 21/08/2014
  2187                                  ilist:
  2188                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2189                                  	;
  2190                                  	; Exception list
  2191                                  	; 25/08/2014	
  2192 00005A9C [1D080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2193 00005AA0 [24080000]              	dd	exc1	
  2194 00005AA4 [2B080000]              	dd 	exc2	
  2195 00005AA8 [32080000]              	dd	exc3	
  2196 00005AAC [36080000]              	dd	exc4	
  2197 00005AB0 [3A080000]              	dd	exc5	
  2198 00005AB4 [3E080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2199 00005AB8 [42080000]              	dd	exc7	
  2200 00005ABC [46080000]              	dd	exc8	
  2201 00005AC0 [4A080000]              	dd	exc9	
  2202 00005AC4 [4E080000]              	dd 	exc10	
  2203 00005AC8 [52080000]              	dd	exc11
  2204 00005ACC [56080000]              	dd	exc12
  2205 00005AD0 [5A080000]              	dd	exc13	; 0Dh, General Protection Fault
  2206 00005AD4 [5E080000]              	dd 	exc14	; 0Eh, Page Fault
  2207 00005AD8 [62080000]              	dd	exc15
  2208 00005ADC [66080000]              	dd	exc16
  2209 00005AE0 [6A080000]              	dd	exc17
  2210 00005AE4 [6E080000]              	dd 	exc18
  2211 00005AE8 [72080000]              	dd	exc19
  2212 00005AEC [76080000]              	dd 	exc20
  2213 00005AF0 [7A080000]              	dd	exc21
  2214 00005AF4 [7E080000]              	dd	exc22
  2215 00005AF8 [82080000]              	dd	exc23
  2216 00005AFC [86080000]              	dd 	exc24
  2217 00005B00 [8A080000]              	dd	exc25
  2218 00005B04 [8E080000]              	dd	exc26
  2219 00005B08 [92080000]              	dd	exc27
  2220 00005B0C [96080000]              	dd 	exc28
  2221 00005B10 [9A080000]              	dd	exc29
  2222 00005B14 [9E080000]              	dd 	exc30
  2223 00005B18 [A2080000]              	dd	exc31
  2224                                  	; Interrupt list
  2225 00005B1C [59060000]              	dd	timer_int	; INT 20h
  2226                                  		;dd	irq0	
  2227 00005B20 [5E0B0000]              	dd	keyb_int	; 27/08/2014
  2228                                  		;dd	irq1
  2229 00005B24 [77070000]              	dd	irq2
  2230                                  		; COM2 int
  2231 00005B28 [7B070000]              	dd	irq3
  2232                                  		; COM1 int
  2233 00005B2C [86070000]              	dd	irq4
  2234 00005B30 [91070000]              	dd	irq5
  2235                                  ;DISKETTE_INT: ;06/02/2015
  2236 00005B34 [EE1F0000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2237                                  		;dd	irq6
  2238                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2239                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2240 00005B38 [0D0B0000]              	dd	default_irq7	; 25/02/2015
  2241                                  		;dd	irq7
  2242                                  ; Real Time Clock Interrupt
  2243 00005B3C [AB090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2244                                  		;dd	irq8	; INT 28h
  2245 00005B40 [A1070000]              	dd	irq9
  2246 00005B44 [A5070000]              	dd	irq10
  2247 00005B48 [A9070000]              	dd	irq11
  2248 00005B4C [AD070000]              	dd	irq12
  2249 00005B50 [B1070000]              	dd	irq13
  2250                                  ;HDISK_INT1:  ;06/02/2015 	
  2251 00005B54 [B9240000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2252                                  		;dd	irq14
  2253                                  ;HDISK_INT2:  ;06/02/2015
  2254 00005B58 [DC240000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2255                                  		;dd	irq15	; INT 2Fh
  2256                                  		; 14/08/2015
  2257 00005B5C [0F310000]              	dd	sysent		; INT 30h (system calls)
  2258                                  	
  2259                                  	;dd	ignore_int
  2260 00005B60 00000000                	dd	0
  2261                                  
  2262                                  ;;;
  2263                                  ;;; 11/03/2015
  2264                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2265                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KYBDATA.INC
  2266                              <1> ; Last Modification: 13/06/2022
  2267                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2268                              <1> ;
  2269                              <1> ; ///////// KEYBOARD DATA ///////////////
  2270                              <1> 
  2271                              <1> ; 11/03/2015
  2272                              <1> ; 05/12/2014
  2273                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2274                              <1> ; 03/06/86  KEYBOARD BIOS
  2275                              <1> 
  2276                              <1> ;---------------------------------------------------------------------------------
  2277                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2278                              <1> ;---------------------------------------------------------------------------------
  2279                              <1> 
  2280                              <1> ;-----	TABLES FOR ALT CASE ------------
  2281                              <1> ;-----	ALT-INPUT-TABLE 
  2282 00005B64 524F50514B          <1> K30:	db	82,79,80,81,75
  2283 00005B69 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2284                              <1> ;-----	SUPER-SHIFT-TABLE 
  2285 00005B6E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2286 00005B74 161718191E1F        <1> 	db	22,23,24,25,30,31
  2287 00005B7A 202122232425        <1> 	db	32,33,34,35,36,37
  2288 00005B80 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2289 00005B86 3132                <1> 	db	49,50
  2290                              <1> 
  2291                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2292                              <1> ;-----	KEY_TABLE 
  2293 00005B88 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2294 00005B89 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2295 00005B8E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2296                              <1> _K6L    equ     $-_K6
  2297                              <1> 
  2298                              <1> ;-----	MASK_TABLE
  2299 00005B90 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2300 00005B91 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2301 00005B96 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2302                              <1> 
  2303                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2304 00005B98 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2305 00005B9E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2306                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2307 00005BA4 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2308 00005BAA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2309 00005BB0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2310 00005BB6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2311 00005BBC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2312 00005BC2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2313 00005BC8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2314 00005BCE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2315                              <1> 	;				;----- FUNCTIONS ------		
  2316 00005BD2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2317 00005BD8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2318 00005BDE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2319 00005BE4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2320 00005BEA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2321                              <1> 
  2322                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2323 00005BF0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2323 00005BF9 39302D3D0809        <1>
  2324 00005BFF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2324 00005C08 705B5D0DFF61736466- <1>
  2324 00005C11 67686A6B6C3B27      <1>
  2325 00005C18 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2325 00005C21 6D2C2E2FFF2AFF20FF  <1>
  2326                              <1> ;-----	LC TABLE SCAN
  2327 00005C2A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2328 00005C2F 4041424344          <1> 	db	64,65,66,67,68
  2329 00005C34 FFFF                <1> 	db	-1,-1			; NL, SL
  2330                              <1> 
  2331                              <1> ;-----	KEYPAD TABLE
  2332 00005C36 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2333 00005C3C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2334 00005C43 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2335                              <1> 
  2336                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2337 00005C48 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2337 00005C51 28295F2B0800        <1>
  2338 00005C57 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2338 00005C60 507B7D0DFF41534446- <1>
  2338 00005C69 47484A4B4C3A22      <1>
  2339 00005C70 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2339 00005C79 4D3C3E3FFF2AFF20FF  <1>
  2340                              <1> ;-----	UC TABLE SCAN
  2341 00005C82 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2342 00005C87 595A5B5C5D          <1> 	db	89,90,91,92,93
  2343 00005C8C FFFF                <1> 	db	-1,-1			; NL, SL
  2344                              <1> 
  2345                              <1> ;-----	NUM STATE TABLE
  2346 00005C8E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2346 00005C97 3233302E            <1>
  2347                              <1> 	;
  2348 00005C9B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2349                              <1> 
  2350                              <1> Align	4
  2351                              <1> ;----------------------------------------
  2352                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2353                              <1> ;----------------------------------------
  2354 00005CA0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2355 00005CA1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2356                              <1> 				; (29h default setting for video mode 3)
  2357                              <1> 				; Mode Select register Bits
  2358                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2359                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2360                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2361                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2362                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2363                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2364                              <1> 				;   BIT 6, 7 - Not Used
  2365                              <1> 
  2366                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2367                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2368                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2369                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2370                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2371                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2372                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2373                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2374                              <1> ; Mode & 37h = Video signal OFF
  2375                              <1> 			
  2376                              <1> 
  2377                              <1> ; 26/08/2014
  2378                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2379                              <1> ; Derived from IBM "pc-at" 
  2380                              <1> ; rombios source code (06/10/1985)
  2381                              <1> ; 'dseg.inc'
  2382                              <1> 
  2383                              <1> ;---------------------------------------;
  2384                              <1> ;	SYSTEM DATA AREA		;
  2385                              <1> ;----------------------------------------
  2386 00005CA2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2387                              <1> 
  2388                              <1> ;----------------------------------------
  2389                              <1> ;	KEYBOARD DATA AREAS		;
  2390                              <1> ;----------------------------------------
  2391                              <1> 
  2392 00005CA3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2393 00005CA4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2394 00005CA5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2395 00005CA6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2396 00005CA7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2397 00005CA8 [B85C0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2398 00005CAC [D85C0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2399 00005CB0 [B85C0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2400 00005CB4 [B85C0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2401                              <1> ; ------  HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY
  2402 00005CB8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2403                              <1> 
  2404                              <1> ; /// End Of KEYBOARD DATA ///
  2265                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2266                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2267                              <1> ; Last Modification: 11/03/2015
  2268                              <1> ;		    (Data section for 'VIDEO.INC')	
  2269                              <1> ;
  2270                              <1> ; ///////// VIDEO DATA ///////////////
  2271                              <1> 
  2272                              <1> video_params:
  2273                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2274                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2275                              <1> 	; VIDEO MODE 3
  2276 00005CD8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2277 00005CDF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2278 00005CE4 00000000            <1> 	db	0,0,0,0
  2279                              <1> 
  2280                              <1> ; /// End Of VIDEO DATA ///
  2266                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2267                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKDATA.INC
  2268                              <1> ; Last Modification: 12/07/2022
  2269                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2270                              <1> ;
  2271                              <1> ; *****************************************************************************
  2272                              <1> ; Ref: Retro UNIX 386 v1.1 'diskdata.inc' modification: 11/07/2022
  2273                              <1> 
  2274                              <1> ;----------------------------------------
  2275                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2276                              <1> ;	REFERENCED BY POST & BIOS	:
  2277                              <1> ;----------------------------------------
  2278                              <1> 
  2279 00005CE8 [4B5D0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2280                              <1> 
  2281                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2282                              <1> ;----------------------------------------------------------------
  2283                              <1> ; DISK_BASE							:
  2284                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2285                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2286                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2287                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2288                              <1> ;----------------------------------------------------------------
  2289                              <1> 
  2290                              <1> ;DISK_BASE:	
  2291                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2292                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2293                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2294                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2295                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2296                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2297                              <1> ;	DB	01BH		; GAP LENGTH
  2298                              <1> ;	DB	0FFH		; DTL
  2299                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2300                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2301                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2302                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2303                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2304                              <1> 
  2305                              <1> ;----------------------------------------
  2306                              <1> ;	ROM BIOS DATA AREAS		:
  2307                              <1> ;----------------------------------------
  2308                              <1> 
  2309                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2310                              <1> 
  2311                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2312                              <1> 
  2313                              <1> ;----------------------------------------
  2314                              <1> ;	DISKETTE DATA AREAS		:
  2315                              <1> ;----------------------------------------
  2316                              <1> 
  2317                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2318                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2319                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2320                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2321                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2322                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2323                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2324                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2325                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2326                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2327                              <1> 
  2328                              <1> ;----------------------------------------
  2329                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2330                              <1> ;----------------------------------------
  2331                              <1> 
  2332                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2333                              <1> 
  2334                              <1> ;----------------------------------------
  2335                              <1> ;	TIMER DATA AREA 		:
  2336                              <1> ;----------------------------------------
  2337                              <1> 
  2338                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2339                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2340                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2341                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2342                              <1> 
  2343                              <1> ;----------------------------------------
  2344                              <1> ;	ADDITIONAL MEDIA DATA		:
  2345                              <1> ;----------------------------------------
  2346                              <1> 
  2347                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2348                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2349                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2350                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2351                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2352                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2353                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2354                              <1> 
  2355                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2356                              <1> 
  2357                              <1> ;--------------------------------------------------------
  2358                              <1> ;	DRIVE TYPE TABLE				:
  2359                              <1> ;--------------------------------------------------------
  2360                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2361                              <1> DR_TYPE:
  2362 00005CEC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2363                              <1>                 ;DW      MD_TBL1
  2364 00005CED [0A5D0000]          <1> 		dd	MD_TBL1
  2365 00005CF1 82                  <1> 		DB	02+BIT7ON
  2366                              <1> 		;DW      MD_TBL2
  2367 00005CF2 [175D0000]          <1>                 dd      MD_TBL2
  2368 00005CF6 02                  <1> DR_DEFAULT:	DB	02
  2369                              <1>                 ;DW      MD_TBL3
  2370 00005CF7 [245D0000]          <1> 		dd      MD_TBL3
  2371 00005CFB 03                  <1> 		DB	03
  2372                              <1>                 ;DW      MD_TBL4
  2373 00005CFC [315D0000]          <1> 		dd      MD_TBL4
  2374 00005D00 84                  <1> 		DB	04+BIT7ON
  2375                              <1>                 ;DW      MD_TBL5
  2376 00005D01 [3E5D0000]          <1> 		dd      MD_TBL5
  2377 00005D05 04                  <1> 		DB	04
  2378                              <1>                 ;DW      MD_TBL6
  2379 00005D06 [4B5D0000]          <1> 		dd      MD_TBL6
  2380                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2381                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2382                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2383                              <1> ;--------------------------------------------------------
  2384                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2385                              <1> ;--------------------------------------------------------
  2386                              <1> ;--------------------------------------------------------
  2387                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2388                              <1> ;--------------------------------------------------------
  2389                              <1> MD_TBL1:        
  2390 00005D0A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2391 00005D0B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2392 00005D0C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2393 00005D0D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2394 00005D0E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2395 00005D0F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2396 00005D10 FF                  <1> 	DB	0FFH		; DTL
  2397 00005D11 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2398 00005D12 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2399 00005D13 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2400 00005D14 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2401 00005D15 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2402 00005D16 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2403                              <1> ;--------------------------------------------------------
  2404                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2405                              <1> ;--------------------------------------------------------
  2406                              <1> MD_TBL2:        
  2407 00005D17 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2408 00005D18 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2409 00005D19 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2410 00005D1A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2411 00005D1B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2412 00005D1C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2413 00005D1D FF                  <1> 	DB	0FFH		; DTL
  2414 00005D1E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2415 00005D1F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2416 00005D20 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2417 00005D21 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2418 00005D22 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2419 00005D23 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2420                              <1> ;--------------------------------------------------------
  2421                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2422                              <1> ;--------------------------------------------------------
  2423                              <1> MD_TBL3:
  2424 00005D24 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2425 00005D25 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2426 00005D26 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2427 00005D27 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2428 00005D28 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2429 00005D29 1B                  <1> 	DB	01BH		; GAP LENGTH
  2430 00005D2A FF                  <1> 	DB	0FFH		; DTL
  2431 00005D2B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2432 00005D2C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2433 00005D2D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2434 00005D2E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2435 00005D2F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2436 00005D30 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2437                              <1> ;--------------------------------------------------------
  2438                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2439                              <1> ;--------------------------------------------------------
  2440                              <1> MD_TBL4:
  2441 00005D31 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2442 00005D32 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2443 00005D33 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2444 00005D34 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2445 00005D35 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2446 00005D36 2A                  <1> 	DB	02AH		; GAP LENGTH
  2447 00005D37 FF                  <1> 	DB	0FFH		; DTL
  2448 00005D38 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2449 00005D39 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2450 00005D3A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2451 00005D3B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2452 00005D3C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2453 00005D3D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2454                              <1> ;--------------------------------------------------------
  2455                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2456                              <1> ;--------------------------------------------------------
  2457                              <1> MD_TBL5:
  2458 00005D3E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2459 00005D3F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2460 00005D40 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2461 00005D41 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2462 00005D42 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2463 00005D43 2A                  <1> 	DB	02AH		; GAP LENGTH
  2464 00005D44 FF                  <1> 	DB	0FFH		; DTL
  2465 00005D45 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2466 00005D46 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2467 00005D47 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2468 00005D48 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2469 00005D49 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2470 00005D4A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2471                              <1> ;--------------------------------------------------------
  2472                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2473                              <1> ;--------------------------------------------------------
  2474                              <1> MD_TBL6:
  2475 00005D4B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2476 00005D4C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2477 00005D4D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2478 00005D4E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2479 00005D4F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2480 00005D50 1B                  <1> 	DB	01BH		; GAP LENGTH
  2481 00005D51 FF                  <1> 	DB	0FFH		; DTL
  2482 00005D52 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2483 00005D53 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2484 00005D54 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2485 00005D55 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2486 00005D56 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2487 00005D57 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2488                              <1> 
  2489                              <1> 
  2490                              <1> ; << diskette.inc >>
  2491                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2492                              <1> ;
  2493                              <1> ;----------------------------------------
  2494                              <1> ;	ROM BIOS DATA AREAS		:
  2495                              <1> ;----------------------------------------
  2496                              <1> 
  2497                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2498                              <1> 
  2499                              <1> ;----------------------------------------
  2500                              <1> ;	FIXED DISK DATA AREAS		:
  2501                              <1> ;----------------------------------------
  2502                              <1> 
  2503                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2504                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2505                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2506                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2507                              <1> 
  2508                              <1> ;----------------------------------------
  2509                              <1> ;	ADDITIONAL MEDIA DATA		:
  2510                              <1> ;----------------------------------------
  2511                              <1> 
  2512                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2513                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2514                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2515                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2516                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2517                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2518                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2519                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2520                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2521                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2522                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2523                              <1> 
  2524                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2525                              <1> ;
  2526                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2527                              <1> 
  2528                              <1> ERR_TBL:
  2529 00005D58 E0                  <1> 	db	NO_ERR
  2530 00005D59 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2531 00005D5D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2532                              <1> 
  2533                              <1> ; 11/07/2022
  2534                              <1> ; 17/12/2014 (mov ax, [cfd])
  2535                              <1> ; 11/12/2014
  2536                              <1> ;cfd:		db 0			; current floppy drive (for GET_PARM)
  2537                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2538                              <1> ;pfd:		db 1			; previous floppy drive (for GET_PARM)
  2539                              <1> 					; (initial value of 'pfd 
  2540                              <1> 					; must be different then 'cfd' value
  2541                              <1> 					; to force updating/initializing
  2542                              <1> 					; current drive parameters) 
  2543                              <1> 
  2544                              <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2545 00005D61 FF                  <1> pfd:		db 0FFh
  2546                              <1> 
  2547                              <1> align 2
  2548                              <1> 
  2549 00005D62 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2550                              <1> 			      ; (170h)
  2551 00005D64 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2552                              <1> 
  2553                              <1> ; 05/01/2015 
  2554 00005D66 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2555                              <1> 
  2556                              <1> ; *****************************************************************************
  2267                                  ;;;
  2268                                  
  2269 00005D67 90                      Align 2
  2270                                  
  2271                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2272 00005D68 00                      boot_drv:    db 0 ; boot drive number (physical)
  2273                                  ; 24/11/2014
  2274 00005D69 00                      drv:	     db 0 
  2275 00005D6A 00                      last_drv:    db 0 ; last hdd
  2276 00005D6B 00                      hdc:         db 0  ; number of hard disk drives
  2277                                  		     ; (present/detected)
  2278                                  ;
  2279                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2280                                  ; Physical drive type & flags
  2281 00005D6C 00                      fd0_type:    db 0  ; floppy drive type
  2282 00005D6D 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2283                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2284                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2285                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2286                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2287 00005D6E 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2288 00005D6F 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2289 00005D70 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2290 00005D71 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2291                                  		     ; bit 0 - Fixed disk access subset supported
  2292                                  		     ; bit 1 - Drive locking and ejecting
  2293                                  		     ; bit 2 - Enhanced disk drive support
  2294                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2295                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2296                                  		     ; will interpret it as 'LBA ready'!)		
  2297                                  
  2298                                  ; 12/07/2022
  2299                                  ; (drv.cylinders, drv.spt, drv.spt will not be used now on)
  2300                                  ; ('diskio.inc')
  2301                                  ; ((spt and heads and cylinder counts will be taken from DPT))
  2302                                  
  2303                                  ; 11/03/2015 - 10/07/2015
  2304                                  ;drv.cylinders: dw 0,0,0,0,0,0,0
  2305                                  ;drv.heads:     dw 0,0,0,0,0,0,0
  2306                                  ;drv.spt:       dw 0,0,0,0,0,0,0
  2307                                  ; 12/07/2022 - 11/03/2015
  2308 00005D72 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2308 00005D7B 000000000000000000-
  2308 00005D84 000000000000000000-
  2308 00005D8D 00                 
  2309 00005D8E 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2310 00005D95 00000000000000          drv.error:     db 0,0,0,0,0,0,0
  2311                                  ;
  2312                                  
  2313                                  ; 27/08/2014
  2314                                  scr_row:
  2315 00005D9C E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2316                                  scr_col:
  2317 00005DA0 00000000                	dd 0
  2318                                  
  2319                                  ;; 14/08/2015
  2320                                  ;;msgPM:
  2321                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2322                                  msgKVER:
  2323                                  	;;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2324                                  	;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [29/04/2022]", 0	
  2325                                  	;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.19 [02/06/2022]", 0
  2326                                  	;;db "Retro UNIX 386 v1 - Kernel v0.2.0.20 [14/06/2022]", 0
  2327                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.21 [12/07/2022]", 0
  2328 00005DA4 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.22 [16/07/2022]", 0
  2328 00005DAD 582033383620763120-
  2328 00005DB6 2D204B65726E656C20-
  2328 00005DBF 76302E322E302E3232-
  2328 00005DC8 205B31362F30372F32-
  2328 00005DD1 3032325D00         
  2329                                  
  2330                                  Align 2
  2331                                  
  2332                                  ; 20/08/2014
  2333                                    ; /* This is the default interrupt "handler" :-) */ 
  2334                                    ; Linux v0.12 (head.s)
  2335                                  int_msg:
  2336 00005DD6 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2336 00005DDF 6E7465727275707420-
  2336 00005DE8 212000             
  2337                                  
  2338 00005DEB 90                      Align 2  
  2339                                  
  2340                                  ; 21/08/2014
  2341                                  timer_msg:
  2342 00005DEC 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2342 00005DF5 542032306829202120-
  2342 00005DFE 54696D657220496E74-
  2342 00005E07 657272757074203A20 
  2343                                  tcountstr:
  2344 00005E10 303030303020            	db "00000 "
  2345 00005E16 00                      	db 0
  2346                                  
  2347 00005E17 90                      Align 2
  2348                                  	; 21/08/2014
  2349                                  exc_msg:
  2350 00005E18 435055206578636570-     	db "CPU exception ! "
  2350 00005E21 74696F6E202120     
  2351                                  excnstr: 		; 25/08/2014
  2352 00005E28 3F3F68202045495020-     	db "??h", "  EIP : "
  2352 00005E31 3A20               
  2353                                  EIPstr: ; 29/08/2014
  2354 00005E33 00<rep Ch>              	times 12 db 0
  2355                                  rtc_msg:
  2356 00005E3F 5265616C2054696D65-     	db "Real Time Clock - "
  2356 00005E48 20436C6F636B202D20 
  2357                                  datestr:
  2358 00005E51 30302F30302F303030-     	db "00/00/0000"
  2358 00005E5A 30                 
  2359 00005E5B 20                      	db " "
  2360                                  daystr:
  2361 00005E5C 44415920                	db "DAY "
  2362                                  timestr:	
  2363 00005E60 30303A30303A3030                db "00:00:00"
  2364 00005E68 20                      	db " "
  2365 00005E69 00                      	db 0 
  2366                                  
  2367                                  daytmp:
  2368                                  	; 28/02/2015
  2369 00005E6A 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2369 00005E73 4F4E20545545205745-
  2369 00005E7C 442054485520465249-
  2369 00005E85 2053415420         
  2370                                  
  2371 00005E8A FF                      ptime_seconds: db 0FFh
  2372                                  
  2373                                  	; 23/02/2015
  2374                                  	; 25/08/2014
  2375                                  ;scounter:
  2376                                  ;	db 5
  2377                                  ;	db 19
  2378                                  
  2379                                  ;; 05/11/2014
  2380                                  ;msg_out_of_memory:
  2381                                  ;	db 	07h, 0Dh, 0Ah
  2382                                  ;	db      'Insufficient memory ! '
  2383                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2384                                  ; 	db	0Dh, 0Ah, 0
  2385                                  	;
  2386                                  setup_error_msg:
  2387 00005E8B 0D0A                    	db 0Dh, 0Ah
  2388 00005E8D 4469736B2053657475-     	db 'Disk Setup Error!' 
  2388 00005E96 70204572726F7221   
  2389 00005E9E 0D0A00                  	db 0Dh, 0Ah,0
  2390                                  
  2391                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2392                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2393                                  ;	  db 0 ; upper left row (for scroll)	
  2394                                  
  2395                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2396                                  ;	  db 24 ; lower right row (for scroll)
  2397                                  
  2398                                  
  2399                                  ; 06/11/2014 (Temporary Data)
  2400                                  ; Memory Information message
  2401                                  ; 14/08/2015
  2402                                  msg_memory_info:
  2403 00005EA1 07                      	db	07h
  2404 00005EA2 0D0A                    	db	0Dh, 0Ah
  2405                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2406 00005EA4 546F74616C206D656D-     	db	"Total memory : "
  2406 00005EAD 6F7279203A20       
  2407                                  mem_total_b_str: ; 10 digits
  2408 00005EB3 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2408 00005EBC 302062797465730D0A 
  2409 00005EC5 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2409 00005ECE 202020202020202020 
  2410                                  mem_total_p_str: ; 7 digits
  2411 00005ED7 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2411 00005EE0 616765730D0A       
  2412 00005EE6 0D0A                    	db 	0Dh, 0Ah
  2413 00005EE8 46726565206D656D6F-     	db	"Free memory  : "
  2413 00005EF1 727920203A20       
  2414                                  free_mem_b_str:  ; 10 digits
  2415 00005EF7 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2415 00005F00 3F2062797465730D0A 
  2416 00005F09 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2416 00005F12 202020202020202020 
  2417                                  free_mem_p_str:  ; 7 digits
  2418 00005F1B 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2418 00005F24 616765730D0A       
  2419 00005F2A 0D0A00                  	db	0Dh, 0Ah, 0
  2420                                  
  2421                                  dsk_ready_msg:
  2422 00005F2D 0D0A                    	db 	0Dh, 0Ah
  2423                                  dsktype:
  2424 00005F2F 6664                    	db	'fd'
  2425                                  dskx:
  2426 00005F31 30                      	db	'0'
  2427 00005F32 20                      	db	20h
  2428 00005F33 697320524541445920-     	db 	'is READY ...'
  2428 00005F3C 2E2E2E             
  2429 00005F3F 00                      	db 	0
  2430                                  nextline:
  2431 00005F40 0D0A00                  	db 	0Dh, 0Ah, 0
  2432                                  
  2433                                  ; KERNEL - SYSINIT Messages
  2434                                  ; 24/08/2015
  2435                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2436                                  ; 14/07/2013
  2437                                  ;kernel_init_err_msg:
  2438                                  ;	db 0Dh, 0Ah
  2439                                  ;	db 07h
  2440                                  ;	db 'Kernel initialization ERROR !'
  2441                                  ;	db 0Dh, 0Ah, 0 
  2442                                  ; 24/08/2015
  2443                                  ;;; (temporary kernel init message has been removed
  2444                                  ;;;  from 'sys_init' code)
  2445                                  ;kernel_init_ok_msg: 
  2446                                  ;	db 0Dh, 0Ah
  2447                                  ;	db 07h
  2448                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2449                                  ;	db 0Dh, 0Ah
  2450                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2451                                  ;	db 0Dh, 0Ah, 0
  2452                                  panic_msg:
  2453 00005F43 0D0A07                  	db 0Dh, 0Ah, 07h
  2454 00005F46 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2454 00005F4F 726E656C2050616E69-
  2454 00005F58 632021             
  2455 00005F5B 0D0A00                  	db 0Dh, 0Ah, 0
  2456                                  etc_init_err_msg:
  2457 00005F5E 0D0A                    	db 0Dh, 0Ah
  2458 00005F60 07                      	db 07h
  2459 00005F61 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2459 00005F6A 74632F696E69742021-
  2459 00005F73 3F                 
  2460 00005F74 0D0A00                  	db 0Dh, 0Ah, 0
  2461                                  
  2462                                  ; 10/05/2015
  2463                                  badsys_msg:
  2464 00005F77 0D0A                    	db 0Dh, 0Ah
  2465 00005F79 07                      	db 07h
  2466 00005F7A 496E76616C69642053-     	db 'Invalid System Call !'
  2466 00005F83 797374656D2043616C-
  2466 00005F8C 6C2021             
  2467 00005F8F 0D0A                    	db 0Dh, 0Ah
  2468 00005F91 4541583A20              	db 'EAX: '
  2469                                  bsys_msg_eax:
  2470 00005F96 303030303030303068      	db '00000000h'
  2471 00005F9F 0D0A                    	db 0Dh, 0Ah
  2472 00005FA1 4549503A20              	db 'EIP: '
  2473                                  bsys_msg_eip:
  2474 00005FA6 303030303030303068      	db '00000000h' 
  2475 00005FAF 0D0A00                  	db 0Dh, 0Ah, 0
  2476                                  
  2477                                  BSYS_M_SIZE equ $ - badsys_msg
  2478                                  
  2479                                  
  2480                                  align 2
  2481                                  
  2482                                  ; EPOCH Variables
  2483                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2484                                  ; 09/04/2013 epoch variables
  2485                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2486                                  ;
  2487 00005FB2 B207                    year: 	dw 1970
  2488                                  ;month: dw 1
  2489                                  ;day: 	dw 1
  2490                                  ;hour: 	dw 0
  2491                                  ;minute: dw 0
  2492                                  ;second: dw 0
  2493                                  ; 02/06/2022
  2494 00005FB4 01                      month:	db 1
  2495 00005FB5 01                      day:	db 1
  2496 00005FB6 01                      hour:	db 1
  2497 00005FB7 01                      minute: db 1
  2498 00005FB8 01                      second:	db 1
  2499 00005FB9 01                      	db 1
  2500                                  
  2501                                  DMonth:
  2502 00005FBA 0000                    	dw 0
  2503 00005FBC 1F00                    	dw 31
  2504 00005FBE 3B00                    	dw 59
  2505 00005FC0 5A00                    	dw 90
  2506 00005FC2 7800                    	dw 120
  2507 00005FC4 9700                    	dw 151
  2508 00005FC6 B500                    	dw 181
  2509 00005FC8 D400                    	dw 212
  2510 00005FCA F300                    	dw 243
  2511 00005FCC 1101                    	dw 273
  2512 00005FCE 3001                    	dw 304
  2513 00005FD0 4E01                    	dw 334
  2514                                  
  2515                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2516 00005FD2 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2517                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2518 00005FD4 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2519                                  		   ;   between 16 MB and 4 GB.
  2520                                  
  2521 00005FD6 90<rep Ah>              align 16
  2522                                  
  2523                                  bss_start:
  2524                                  
  2525                                  ABSOLUTE bss_start
  2526                                  
  2527                                  	; 11/03/2015
  2528                                  	; Interrupt Descriptor Table (20/08/2014)
  2529                                  idt:
  2530 00005FE0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2531                                  idt_end:
  2532                                  
  2533                                  ;alignb 4
  2534                                  
  2535                                  task_state_segment:
  2536                                  	; 24/03/2015
  2537 000061E0 ????                    tss.link:   resw 1
  2538 000061E2 ????                    	    resw 1
  2539                                  ; tss offset 4	
  2540 000061E4 ????????                tss.esp0:   resd 1
  2541 000061E8 ????                    tss.ss0:    resw 1
  2542 000061EA ????                    	    resw 1	
  2543 000061EC ????????                tss.esp1:   resd 1
  2544 000061F0 ????                    tss.ss1:    resw 1
  2545 000061F2 ????                    	    resw 1 	
  2546 000061F4 ????????                tss.esp2:   resd 1
  2547 000061F8 ????                    tss.ss2:    resw 1
  2548 000061FA ????                    	    resw 1
  2549                                  ; tss offset 28
  2550 000061FC ????????                tss.CR3:    resd 1
  2551 00006200 ????????                tss.eip:    resd 1
  2552 00006204 ????????                tss.eflags: resd 1
  2553                                  ; tss offset 40
  2554 00006208 ????????                tss.eax:    resd 1		 		
  2555 0000620C ????????                tss.ecx:    resd 1
  2556 00006210 ????????                tss.edx:    resd 1
  2557 00006214 ????????                tss.ebx:    resd 1
  2558 00006218 ????????                tss.esp:    resd 1
  2559 0000621C ????????                tss.ebp:    resd 1
  2560 00006220 ????????                tss.esi:    resd 1
  2561 00006224 ????????                tss.edi:    resd 1
  2562                                  ; tss offset 72
  2563 00006228 ????                    tss.ES:     resw 1
  2564 0000622A ????                    	    resw 1	
  2565 0000622C ????                    tss.CS:	    resw 1
  2566 0000622E ????                    	    resw 1
  2567 00006230 ????                    tss.SS:	    resw 1
  2568 00006232 ????                    	    resw 1
  2569 00006234 ????                    tss.DS:	    resw 1
  2570 00006236 ????                    	    resw 1
  2571 00006238 ????                    tss.FS:	    resw 1
  2572 0000623A ????                    	    resw 1
  2573 0000623C ????                    tss.GS:	    resw 1
  2574 0000623E ????                    	    resw 1		
  2575 00006240 ????                    tss.LDTR:   resw 1
  2576 00006242 ????                    	    resw 1
  2577                                  ; tss offset 100		
  2578 00006244 ????                    	    resw 1		
  2579 00006246 ????                    tss.IOPB:   resw 1
  2580                                  ; tss offset 104 
  2581                                  tss_end:
  2582                                  
  2583 00006248 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2584                                  		    ; (Physical address = Virtual address)	 	
  2585 0000624C ????????                memory_size: resd 1 ; memory size in pages
  2586 00006250 ????????                free_pages:  resd 1 ; number of free pages		
  2587 00006254 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2588                                  		    ; first free page search
  2589 00006258 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2590                                  		    ; next free page search will be
  2591                                  		    ; stopped after it. (end of M.A.T.)
  2592 0000625C ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2593                                  		    ; first free page search
  2594                                  		    ; will be started on it. (for user)
  2595 00006260 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2596                                  
  2597                                  ;;;
  2598                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2599                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2600 00006264 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2601                                  		    ; NOTE: active page only
  2602 00006266 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2603                                  active_page: 
  2604 00006276 ??                      ptty: 	     resb 1 ; current tty
  2605                                  ; 01/07/2015
  2606 00006277 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2607                                  ; 26/10/2015
  2608                                  ; 07/09/2014
  2609 00006278 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2610                                  
  2611                                  ; 21/08/2014
  2612 0000628C ????????                tcount:	     resd 1
  2613                                  
  2614                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2615 00006290 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2616                                  
  2617                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2618                                  ; (open mode locks for pseudo TTYs)
  2619                                  ; [ major tty locks (return error in any conflicts) ]
  2620 00006294 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2621                                  
  2622                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2623                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2624 000062A8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2625                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2626                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2627                                  ;; 0 means serial port is not available 
  2628                                  ;;comprm: ; 25/06/2014
  2629 000062B2 ??                      com1p:       resb 1 ;;0E3h
  2630 000062B3 ??                      com2p:       resb 1 ;;0E3h
  2631                                  
  2632                                  ; 17/11/2015
  2633                                  ; request for response (from the terminal)	
  2634 000062B4 ????                    req_resp:     resw 1 			
  2635                                  ; 07/11/2015
  2636 000062B6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2637                                  		    ; (0= COM1, 1= COM2)
  2638                                  ; 09/11/2015
  2639 000062B7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2640                                  ; 07/11/2015
  2641 000062B8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2642 000062BA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2643                                  
  2644                                  ; 23/10/2015
  2645                                  ; SERIAL PORTS - COMMUNICATION MODES
  2646                                  ; (Retro UNIX 386 v1 feature only!)
  2647                                  ; 0 - command mode (default/initial mode)
  2648                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2649                                  ;;; communication modes for future versions:  
  2650                                  ; // 2 - keyboard mode (ascii+scancode input)
  2651                                  ; // 3 - mouse mode
  2652                                  ; // 4 - device control (output) mode
  2653                                  ; VALID COMMANDS for current version:
  2654                                  ; 	'LOGIN'
  2655                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2656                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2657                                  ;  Login response: db 0FFh, 'login', 0
  2658                                  ;	 ("login request accepted, wait for login prompt") 
  2659                                  ; When a login requests is received and acknowledged (by
  2660                                  ; serial port interrupt handler (communication procedure),
  2661                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2662                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2663                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2664                                  ; 
  2665                                  ; 'sys connect' system call is used to change communication mode
  2666                                  ; except 'LOGIN' command which is used to start terminal mode
  2667                                  ; by using (COM port) terminal.
  2668                                  
  2669                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2670                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2671                                  ;com1mode:    resb 1 ; communication mode for COM1
  2672                                  ;com1com:     resb 1 ; communication command for COM1
  2673                                  ;com2mode:    resb 1 ; communication mode for COM1
  2674                                  ;com2com      resb 1 ; communication command for COM1
  2675                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2676                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2677                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2678                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2679                                  
  2680                                  ; 22/08/2014 (RTC)
  2681                                  ; (Packed BCD)
  2682 000062BC ??                      time_seconds: resb 1
  2683 000062BD ??                      time_minutes: resb 1
  2684 000062BE ??                      time_hours:   resb 1
  2685 000062BF ??                      date_wday:    resb 1
  2686 000062C0 ??                      date_day:     resb 1
  2687 000062C1 ??                      date_month:   resb 1			
  2688 000062C2 ??                      date_year:    resb 1
  2689 000062C3 ??                      date_century: resb 1
  2690                                  
  2691                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2692                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKBSS.INC
  2693                              <1> ; Last Modification: 12/07/2022
  2694                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC') 
  2695                              <1> ;
  2696                              <1> ; *****************************************************************************
  2697                              <1> ; Ref: Retro UNIX 386 v1.1 'disbss.inc' modification: 10/07/2022
  2698                              <1> 
  2699                              <1> 
  2700                              <1> alignb 2
  2701                              <1> 
  2702                              <1> ;----------------------------------------
  2703                              <1> ;	TIMER DATA AREA 		:
  2704                              <1> ;----------------------------------------
  2705                              <1> 
  2706                              <1> TIMER_LH:	; 16/02/205
  2707 000062C4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2708 000062C6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2709 000062C8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2710                              <1> 
  2711                              <1> ;----------------------------------------
  2712                              <1> ;	DISKETTE DATA AREAS		:
  2713                              <1> ;----------------------------------------
  2714                              <1> 
  2715 000062C9 ??                  <1> SEEK_STATUS:	resb	1
  2716 000062CA ??                  <1> MOTOR_STATUS:	resb	1
  2717 000062CB ??                  <1> MOTOR_COUNT:	resb	1
  2718 000062CC ??                  <1> DSKETTE_STATUS:	resb	1
  2719 000062CD ??????????????      <1> NEC_STATUS:	resb	7
  2720                              <1> 
  2721                              <1> ;----------------------------------------
  2722                              <1> ;	ADDITIONAL MEDIA DATA		:
  2723                              <1> ;----------------------------------------
  2724                              <1> 
  2725 000062D4 ??                  <1> LASTRATE:	resb 	1
  2726 000062D5 ??                  <1> HF_STATUS:	resb 	1
  2727                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2728 000062D6 ??                  <1> HF_INT_FLAG:	resb	1
  2729                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2730                              <1> ;DSK_STATE:	resb 	4
  2731 000062D7 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2732 000062D9 ????                <1> DSK_TRK:	resb 	2
  2733                              <1> 
  2734                              <1> ;----------------------------------------
  2735                              <1> ;	FIXED DISK DATA AREAS		:
  2736                              <1> ;----------------------------------------
  2737                              <1> 
  2738 000062DB ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2739 000062DC ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2740 000062DD ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2741                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2742                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2743                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2744                              <1> 
  2745 000062DE ????                <1> alignb 4
  2746                              <1> 
  2747                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2748                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2749                              <1> HF_TBL_VEC: ; 22/12/2014	
  2750 000062E0 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2751 000062E4 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2752 000062E8 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2753 000062EC ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2754                              <1> 
  2755                              <1> ; 03/01/2015
  2756 000062F0 ??                  <1> LBAMode:     	resb	1
  2757                              <1> 
  2758                              <1> ; *****************************************************************************
  2692                                  
  2693                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2694                                  
  2695                                  ;alignb 2
  2696                                  
  2697                                  ; 27/02/2022
  2698                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2699                                  
  2700                                  ; 23/02/2022
  2701                                  ;; Memory (swap) Data (11/03/2015)
  2702                                  ; 09/03/2015
  2703                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2704                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2705                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2706                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2707                                  ;swpd_next:  resd 1 ; next free page block
  2708                                  ;swpd_last:  resd 1 ; last swap page block	
  2709                                  
  2710 000062F1 ??????                  alignb 4
  2711                                  
  2712                                  ; 10/07/2015
  2713                                  ; 28/08/2014
  2714 000062F4 ????????                error_code:	resd 1
  2715                                  ; 29/08/2014
  2716 000062F8 ????????                FaultOffset: 	resd 1
  2717                                  ; 21/09/2015
  2718 000062FC ????????                PF_Count:	resd 1	; total page fault count
  2719                                  		       	; (for debugging - page fault analyze)
  2720                                  		 	; 'page _fault_handler' (memory.inc)
  2721                                  			; 'sysgeterr' (u9.s)
  2722                                  ; 23/02/2022
  2723 00006300 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2724                                  			;  for a system call in next retro unix 386 version)
  2725                                  			; -2 ticks per second-
  2726                                  ;; 21/08/2015
  2727                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2728                                  
  2729                                  ; 27/02/2022
  2730                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2731                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYSX.INC (ux.s)
  2732                              <1> ; Last Modification: 15/07/2022
  2733                              <1> ;
  2734                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2735                              <1> ; (Modified from 
  2736                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2737                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2738                              <1> ; ----------------------------------------------------------------------------
  2739                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2740                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2741                              <1> ; <Bell Laboratories (17/3/1972)>
  2742                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2743                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2744                              <1> ; ****************************************************************************
  2745                              <1> ; 13/11/2015
  2746                              <1> 
  2747                              <1> alignb 2
  2748                              <1> 
  2749                              <1> inode:
  2750                              <1> 	; 11/03/2013. 
  2751                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2752                              <1> 	;i.
  2753                              <1> 
  2754 00006304 ????                <1> 	i.flgs:	 resw 1
  2755 00006306 ??                  <1> 	i.nlks:	 resb 1
  2756 00006307 ??                  <1> 	i.uid:	 resb 1
  2757 00006308 ????                <1>         i.size:  resw 1 ; size
  2758 0000630A <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2759 0000631A ????????            <1> 	i.ctim:	 resd 1
  2760 0000631E ????????            <1> 	i.mtim:	 resd 1
  2761 00006322 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2762                              <1> 
  2763                              <1> I_SIZE	equ $ - inode 
  2764                              <1> 
  2765                              <1> process:
  2766                              <1> 	; 26/02/2022
  2767                              <1> 	; 04/02/2022
  2768                              <1> 	; 06/05/2015
  2769                              <1> 	; 11/03/2013 - 05/02/2014
  2770                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2771                              <1> 	;p.
  2772                              <1> 	
  2773 00006324 <res 20h>           <1>         p.pid:   resw nproc
  2774 00006344 <res 20h>           <1>         p.ppid:  resw nproc
  2775                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2776 00006364 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2777                              <1> 	; 26/02/2022 (p.waitc is not used)
  2778                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2779 00006374 <res 10h>           <1> 	p.link:	 resb nproc
  2780 00006384 <res 10h>           <1> 	p.stat:	 resb nproc
  2781                              <1> 
  2782                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2783 00006394 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2784                              <1> 			    ; 'user' structure	
  2785                              <1> 
  2786                              <1> 
  2787                              <1> P_SIZE	equ $ - process
  2788                              <1> 
  2789                              <1> 
  2790                              <1> ; fsp table (original UNIX v1)
  2791                              <1> ;
  2792                              <1> ;Entry
  2793                              <1> ;          15                                      0
  2794                              <1> ;  1     |---|---------------------------------------|
  2795                              <1> ;        |r/w|       i-number of open file           |
  2796                              <1> ;        |---|---------------------------------------| 
  2797                              <1> ;        |               device number               |
  2798                              <1> ;        |-------------------------------------------|
  2799                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2800                              <1> ;        |-------------------------------------------| 
  2801                              <1> ;        |  flag that says    | number of processes  |
  2802                              <1> ;        |   file deleted     | that have file open  |
  2803                              <1> ;        |-------------------------------------------| 
  2804                              <1> ;  2     |                                           |
  2805                              <1> ;        |-------------------------------------------| 
  2806                              <1> ;        |                                           |
  2807                              <1> ;        |-------------------------------------------|
  2808                              <1> ;        |                                           |
  2809                              <1> ;        |-------------------------------------------|
  2810                              <1> ;        |                                           |
  2811                              <1> ;        |-------------------------------------------| 
  2812                              <1> ;  3     |                                           | 
  2813                              <1> ;        |                                           |  
  2814                              <1> ;
  2815                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2816                              <1> 
  2817                              <1> 
  2818                              <1> ; 15/04/2015
  2819 000063D4 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2820 000065C8 <res 28h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2821 000065F0 ????                <1> ii:	 resw 1
  2822 000065F2 ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2823 000065F4 ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2824                              <1> ; 18/05/2015
  2825                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2826                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2827                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2828                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2829                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2830                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2831                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2832                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2833                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2834                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2835                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2836 000065F6 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2837                              <1> 	        ; as above, for physical drives numbers in following table
  2838 000065F7 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2839                              <1> ; 15/04/2015
  2840                              <1> ;active: resb 1 ; 15/07/2022
  2841                              <1> ;	 resb 1 ; 09/06/2015
  2842 000065F8 ????                <1> mnti:	 resw 1
  2843 000065FA ????                <1> mntp:	 resw 1 ; 14/05/2022 ; (parent dir inumber of [mnti])
  2844 000065FC ????                <1> mpid:	 resw 1
  2845 000065FE ????                <1> rootdir: resw 1
  2846                              <1> ; 14/02/2014
  2847                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2848                              <1> ;		      Single level run queue
  2849                              <1> ;		      (in order to solve sleep/wakeup lock)
  2850 00006600 ????                <1> runq:	 resw 1
  2851 00006602 ??                  <1> imod:	 resb 1
  2852 00006603 ??                  <1> smod:	 resb 1
  2853 00006604 ??                  <1> mmod:	 resb 1
  2854 00006605 ??                  <1> sysflg:	 resb 1
  2855                              <1> 
  2856 00006606 ????                <1> alignb 4
  2857                              <1> 
  2858                              <1> user:
  2859                              <1> 	; 18/10/2015
  2860                              <1> 	; 12/10/2015
  2861                              <1> 	; 21/09/2015
  2862                              <1> 	; 24/07/2015
  2863                              <1> 	; 16/06/2015
  2864                              <1> 	; 09/06/2015
  2865                              <1> 	; 11/05/2015
  2866                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2867                              <1> 	; 10/10/2013
  2868                              <1> 	; 11/03/2013. 
  2869                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2870                              <1> 	;u.
  2871                              <1> 
  2872 00006608 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2873 0000660C ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2874 00006610 ????????            <1> 	u.r0:	  resd 1 ; eax
  2875 00006614 ????                <1> 	u.cdir:	  resw 1
  2876 00006616 <res Ah>            <1> 	u.fp:	  resb 10
  2877 00006620 ????????            <1> 	u.fofp:	  resd 1
  2878 00006624 ????????            <1> 	u.dirp:	  resd 1
  2879 00006628 ????????            <1> 	u.namep:  resd 1
  2880 0000662C ????????            <1> 	u.off:	  resd 1
  2881 00006630 ????????            <1> 	u.base:	  resd 1
  2882 00006634 ????????            <1> 	u.count:  resd 1
  2883 00006638 ????????            <1> 	u.nread:  resd 1
  2884 0000663C ????????            <1> 	u.break:  resd 1 ; break
  2885 00006640 ????                <1> 	u.ttyp:	  resw 1 
  2886 00006642 <res Ah>            <1> 	u.dirbuf: resb 10
  2887                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2888 0000664C ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2889 0000664D ??                  <1> 	u.pri:	  resb 1 ; 
  2890 0000664E ????                <1> 	u.intr:	  resw 1
  2891 00006650 ????                <1> 	u.quit:	  resw 1
  2892                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2893 00006652 ????                <1> 	u.ilgins: resw 1
  2894 00006654 ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2895 00006656 ??                  <1> 	u.uid:	  resb 1 ; uid
  2896 00006657 ??                  <1> 	u.ruid:	  resb 1
  2897 00006658 ??                  <1> 	u.bsys:	  resb 1
  2898 00006659 ??                  <1> 	u.uno:	  resb 1
  2899 0000665A ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2900                              <1> 	; tty number (rtty, rcvt, wtty)
  2901 0000665E ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2902                              <1> 	; last error number
  2903 0000665F ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2904                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2905 00006663 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2906 00006667 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2907 0000666B ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2908 0000666F ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2909                              <1> 	;u.pncount: resw 1 
  2910                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2911                              <1> 	;u.pnbase:  resd 1 
  2912                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2913                              <1> 			 ; 09/06/2015
  2914 00006671 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2915 00006672 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2916                              <1> 			 ; 24/07/2015 - 24/06/2015
  2917                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2918                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2919                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2920                              <1>  			 ; 24/06/2015	  	
  2921                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2922                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2923                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2924 00006673 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2925                              <1> 
  2926 00006677 ??                  <1> alignb 4
  2927                              <1> 
  2928                              <1> U_SIZE	equ $ - user
  2929                              <1> 
  2930                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2931 00006678 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2932 0000667C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2933 00006680 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2934 00006684 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2935 00006686 ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2936 00006688 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2937                              <1> 
  2938                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2939                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2940 0000668C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2941 0000668D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2942 0000668E ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2943 0000668F ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2944                              <1> 
  2945                              <1> ;alignb 4
  2946                              <1> 
  2947                              <1> ; 22/08/2015
  2948 00006690 <res 1040h>         <1> buffer: resb nbuf * 520
  2949                              <1> 
  2950 000076D0 ????????????????    <1> sb0:	resd 2
  2951                              <1> ;s:
  2952                              <1> ; (root disk) super block buffer
  2953                              <1> systm:
  2954                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2955                              <1> 	; 11/03/2013. 
  2956                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2957                              <1> 	;s.
  2958                              <1> 
  2959 000076D8 ????                <1> 	resw 1
  2960 000076DA <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2961 00007842 ????                <1> 	resw 1
  2962 00007844 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2963                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2964 00007864 ????????            <1> 	s.time:	 resd 1
  2965 00007868 ????????            <1> 	s.syst:	 resd 1
  2966 0000786C ????????            <1>         s.wait_: resd 1 ; wait
  2967 00007870 ????????            <1> 	s.idlet: resd 1
  2968 00007874 ????????            <1> 	s.chrgt: resd 1
  2969 00007878 ????                <1> 	s.drerr: resw 1
  2970                              <1> 
  2971                              <1> S_SIZE	equ $ - systm
  2972                              <1> 
  2973 0000787A <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2974                              <1> 
  2975 000078D8 ????????????????    <1> sb1:	resd 2
  2976                              <1> ; (mounted disk) super block buffer
  2977                              <1> mount:	
  2978 000078E0 <res 200h>          <1> 	resb 512  ; 03/06/2015
  2979                              <1> 
  2980                              <1> ;/ ux -- unix
  2981                              <1> ;
  2982                              <1> ;systm:
  2983                              <1> ;
  2984                              <1> ;	.=.+2
  2985                              <1> ;	.=.+128.
  2986                              <1> ;	.=.+2
  2987                              <1> ;	.=.+64.
  2988                              <1> ;	s.time: .=.+4
  2989                              <1> ;	s.syst: .=.+4
  2990                              <1> ;	s.wait: .=.+4
  2991                              <1> ;	s.idlet:.=.+4
  2992                              <1> ;	s.chrgt:.=.+4
  2993                              <1> ;	s.drerr:.=.+2
  2994                              <1> ;inode:
  2995                              <1> ;	i.flgs: .=.+2
  2996                              <1> ;	i.nlks: .=.+1
  2997                              <1> ;	i.uid:  .=.+1
  2998                              <1> ;	i.size: .=.+2
  2999                              <1> ;	i.dskp: .=.+16.
  3000                              <1> ;	i.ctim: .=.+4
  3001                              <1> ;	i.mtim: .=.+4
  3002                              <1> ;	. = inode+32.
  3003                              <1> ;mount:	.=.+1024.
  3004                              <1> ;proc:
  3005                              <1> ;	p.pid:  .=.+[2*nproc]
  3006                              <1> ;	p.dska: .=.+[2*nproc]
  3007                              <1> ;	p.ppid: .=.+[2*nproc]
  3008                              <1> ;	p.break:.=.+[2*nproc]
  3009                              <1> ;	p.link: .=.+nproc
  3010                              <1> ;	p.stat: .=.+nproc
  3011                              <1> ;tty:
  3012                              <1> ;	. = .+[ntty*8.]
  3013                              <1> ;fsp:	.=.+[nfiles*8.]
  3014                              <1> ;bufp:	.=.+[nbuf*2]+6
  3015                              <1> ;sb0:	.=.+8
  3016                              <1> ;sb1:	.=.+8
  3017                              <1> ;swp:	.=.+8
  3018                              <1> ;ii:	.=.+2
  3019                              <1> ;idev:	.=.+2
  3020                              <1> ;cdev:	.=.+2
  3021                              <1> ;deverr: .=.+12.
  3022                              <1> ;active: .=.+2
  3023                              <1> ;rfap:	.=.+2
  3024                              <1> ;rkap:	.=.+2
  3025                              <1> ;tcap:	.=.+2
  3026                              <1> ;tcstate:.=.+2
  3027                              <1> ;tcerrc: .=.+2
  3028                              <1> ;mnti:	.=.+2
  3029                              <1> ;mntd:	.=.+2
  3030                              <1> ;mpid:	.=.+2
  3031                              <1> ;clockp: .=.+2
  3032                              <1> ;rootdir:.=.+2
  3033                              <1> ;toutt:	.=.+16.
  3034                              <1> ;touts: .=.+32.
  3035                              <1> ;runq:	.=.+6
  3036                              <1> ;
  3037                              <1> ;wlist:	.=.+40.
  3038                              <1> ;cc:	.=.+30.
  3039                              <1> ;cf:	.=.+31.
  3040                              <1> ;cl:	.=.+31.
  3041                              <1> ;clist:	.=.+510.
  3042                              <1> ;imod:	.=.+1
  3043                              <1> ;smod:	.=.+1
  3044                              <1> ;mmod:	.=.+1
  3045                              <1> ;uquant: .=.+1
  3046                              <1> ;sysflg: .=.+1
  3047                              <1> ;pptiflg:.=.+1
  3048                              <1> ;ttyoch: .=.+1
  3049                              <1> ; .even
  3050                              <1> ; .=.+100.; sstack:
  3051                              <1> ;buffer: .=.+[ntty*140.]
  3052                              <1> ;	.=.+[nbuf*520.]
  3053                              <1> ;
  3054                              <1> ; . = core-64.
  3055                              <1> ;user:
  3056                              <1> ;	u.sp:    .=.+2
  3057                              <1> ;	u.usp:   .=.+2
  3058                              <1> ;	u.r0:    .=.+2
  3059                              <1> ;	u.cdir:  .=.+2
  3060                              <1> ;	u.fp:    .=.+10.
  3061                              <1> ;	u.fofp:  .=.+2
  3062                              <1> ;	u.dirp:  .=.+2
  3063                              <1> ;	u.namep: .=.+2
  3064                              <1> ;	u.off:   .=.+2
  3065                              <1> ;	u.base:  .=.+2
  3066                              <1> ;	u.count: .=.+2
  3067                              <1> ;	u.nread: .=.+2
  3068                              <1> ;	u.break: .=.+2
  3069                              <1> ;	u.ttyp:  .=.+2
  3070                              <1> ;	u.dirbuf:.=.+10.
  3071                              <1> ;	u.pri:   .=.+2
  3072                              <1> ;	u.intr:  .=.+2
  3073                              <1> ;	u.quit:  .=.+2
  3074                              <1> ;	u.emt:   .=.+2
  3075                              <1> ;	u.ilgins:.=.+2
  3076                              <1> ;	u.cdev:  .=.+2
  3077                              <1> ;	u.uid:   .=.+1
  3078                              <1> ;	u.ruid:  .=.+1
  3079                              <1> ;	u.bsys:  .=.+1
  3080                              <1> ;	u.uno:   .=.+1
  3081                              <1> ;. = core
  2731                                  
  2732                                  bss_end:
  2733                                  
  2734                                  ; 27/02/2022
  2735                                  BSS_SIZE equ bss_end - bss_start
  2736                                  
  2737                                  ; 27/12/2013
  2738                                  _end:  ; end of kernel code (and read only data, just before bss)
