     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.21
     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: 12/07/2022 ] ; 2022 modification (previous: 14/06/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                                  ; 12/07/2022 (v0.2.0.21)
    24                                  ; 15/05/2022 - 14/06/2022 (v0.2.0.20)
    25                                  ; 04/02/2016 (v0.2.0.17) - 29/04/2022 (v0.2.0.18) - 09/05/2022 (v0.2.0.19)
    26                                  
    27                                  ; Assembler: NASM 2.15
    28                                  ;	nasm unix386.s -l unix386.lst -o unix386 -Z error.txt
    29                                  
    30                                  ; 24/12/2013
    31                                  
    32                                  ; Entering protected mode:
    33                                  ; Derived from 'simple_asm.txt' source code file and 
    34                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    35                                  ; (gregor.brunmar@home.se)
    36                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    37                                  ;
    38                                  
    39                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    40                                  ; by Michael Chourdakis (2009) 
    41                                  ; http://www.codeproject.com/Articles/45788/
    42                                  ; http://www.michaelchourdakis.com
    43                                  ;
    44                                  
    45                                  ; Global Descriptor Table:
    46                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    47                                  ; by Linus Torvalds (1991-1992)
    48                                  ;
    49                                  
    50                                  KLOAD	equ 10000h ; Kernel loading address
    51                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    52                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    53                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    54                                  ; 19/03/2015
    55                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    56                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    57                                  ; 24/03/2015
    58                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    59                                  ; 19/03/2015
    60                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    61                                  		     ; (at the end of the 1st 4MB)
    62                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    63                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    64                                  
    65                                  ; 27/12/2013
    66                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    67                                  
    68                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    69                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    70                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    71                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    72                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    73                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    74                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    75                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    76                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    77                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    78                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    79                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    80                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    81                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    82                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    83                                  ;----------------------------------------
    84                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    85                                  ;-----------------------------------------------------------------------------
    86                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    87                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    88                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    89                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    90                                  
    91                                  ; Memory Allocation Table Address
    92                                  ; 05/11/2014
    93                                  ; 31/10/2014
    94                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    95                                  					; the 1st 1 MB memory space.
    96                                  					; (This address must be aligned
    97                                  					;  on 128 KB boundary, if it will be
    98                                  					;  changed later.)
    99                                  					; ((lower 17 bits of 32 bit M.A.T.
   100                                  					;   address must be ZERO)).
   101                                  					; ((((Reason: 32 bit allocation 
   102                                  					;     instructions, dword steps)))
   103                                  					; (((byte >> 12 --> page >> 5)))  
   104                                  ;04/11/2014	
   105                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   106                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   107                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   108                                  ;
   109                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   110                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   111                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   112                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   113                                  
   114                                  ; 17/02/2015 (unix386.s)
   115                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   116                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   117                                  ;
   118                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   119                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   120                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   121                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   122                                  
   123                                  
   124                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   125                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   126                                  ;
   127                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   128                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   129                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   130                                  		      ; otherwise it is standard FDPT with physical values 	
   131                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   132                                  		      ; (obsolete for IDE/ATA drives)
   133                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   134                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   135                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   136                                  			; Bit 4 : Reserved. Always 0
   137                                  			; Bit 3 : Set to 1 if more than 8 heads
   138                                  			; Bit 2-0 : Reserved. Alsways 0
   139                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   140                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   141                                  
   142                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   143                                  ; (11 bytes long) will be used by diskette handler/bios
   144                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   145                                  
   146                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   147                                  
   148                                  [ORG 0] 
   149                                  	; 12/11/2014
   150                                  	; Save boot drive number (that is default root drive)
   151 00000000 8816[285E]              	mov	[boot_drv], dl ; physical drv number
   152                                  
   153                                  	; Determine installed memory
   154                                  	; 31/10/2014
   155                                  	;
   156 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   157 00000007 CD15                    	int	15h	   ; for large configurations
   158 00000009 7308                    	jnc	short chk_ms
   159 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   160 0000000D CD15                    	int	15h
   161                                  	;	   
   162                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   163                                  	;out	70h, al ; select CMOS register
   164                                  	;in	al, 71h ; read data (1 byte)
   165                                  	;mov	cl, al
   166                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   167                                  	;out	70h, al ; select CMOS register
   168                                  	;in	al, 71h ; read data (1 byte)
   169                                  	;mov	ch, al
   170                                   	;      
   171 0000000F 89C1                    	mov	cx, ax
   172 00000011 31D2                    	xor	dx, dx
   173                                  chk_ms:
   174 00000013 890E[9260]              	mov	[mem_1m_1k], cx
   175 00000017 8916[9460]              	mov	[mem_16m_64k], dx
   176                                  	; 05/11/2014
   177                                  	;and	dx, dx
   178                                  	;jz	short L2
   179 0000001B 81F90004                        cmp     cx, 1024
   180 0000001F 7351                    	jnb	short L0
   181                                  		 ; insufficient memory_error	
   182                                  		 ; Minimum 2 MB memory is needed... 
   183                                  	; 05/11/2014
   184                                  	; (real mode error printing)
   185 00000021 FB                      	sti
   186 00000022 BE[3600]                	mov	si, msg_out_of_memory
   187 00000025 BB0700                  	mov	bx, 7
   188 00000028 B40E                    	mov	ah, 0Eh	; write tty
   189                                  oom_1:
   190 0000002A AC                      	lodsb
   191 0000002B 08C0                    	or	al, al
   192 0000002D 7404                    	jz	short oom_2
   193 0000002F CD10                    	int	10h
   194 00000031 EBF7                    	jmp	short oom_1
   195                                  oom_2:
   196 00000033 F4                              hlt
   197 00000034 EBFD                    	jmp	short oom_2
   198                                  
   199                                  ; 04/02/2022
   200                                  ; 05/11/2014
   201                                  msg_out_of_memory:
   202 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   203 00000039 496E73756666696369-             db      'Insufficient memory !'
   203 00000042 656E74206D656D6F72-
   203 0000004B 792021             
   204 0000004E 0D0A                    	db	0Dh, 0Ah
   205                                  _int13h_48h_buffer: 
   206                                  	; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc')
   207 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   207 00000059 324D42206D656D6F72-
   207 00000062 79206973206E656564-
   207 0000006B 65642E29           
   208 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   209                                  
   210                                  L0:
   211                                  %include 'diskinit.inc' ; 07/03/2015
   212                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKINIT.INC
   213                              <1> ; Last Modification: 12/07/2022
   214                              <1> ; ************************************************************************
   215                              <1> ; Ref: Retro UNIX 386 v1.1 'diskinit.inc' modification: 12/07/2022
   216                              <1> 
   217                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   218                              <1> 
   219                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   220                              <1> 
   221                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18)
   222                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   223                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   224                              <1> ;L0:
   225                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   226                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   227 00000072 BA7F00              <1> 	mov	dx, 7Fh
   228                              <1> L1:	
   229 00000075 FEC2                <1> 	inc	dl
   230 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   231                              <1> 			; Phoenix EDD v1.1 - EDD v3
   232 00000079 BBAA55              <1> 	mov	bx, 55AAh
   233 0000007C CD13                <1> 	int 	13h
   234 0000007E 721A                <1> 	jc	short L2
   235                              <1> 
   236 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   237 00000084 7514                <1> 	jne	short L2
   238 00000086 FE06[2B5E]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   239 0000008A 8816[2A5E]          <1>         mov     [last_drv], dl  ; last hard disk number
   240 0000008E BB[AE5D]            <1> 	mov	bx, hd0_type - 80h
   241 00000091 01D3                <1> 	add	bx, dx	 
   242 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   243                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   244                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   245                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   246                              <1>                          ;            (EDD) ready (DPTE ready)
   247                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   248                              <1>                          ;            (EDD-3)
   249                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   250 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   251 00000098 72DB                <1> 	jb	short L1
   252                              <1> L2:
   253                              <1> 	; 23/11/2014
   254                              <1> 	; 19/11/2014
   255 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   256                              <1> 	; 04/02/2016 (esi -> si)
   257 0000009C BE[2C5E]            <1> 	mov	si, fd0_type
   258                              <1> L3:
   259                              <1> 	; 14/01/2015
   260 0000009F 8816[295E]          <1> 	mov	[drv], dl
   261                              <1> 	;
   262 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   263 000000A5 CD13                <1> 	int	13h	
   264 000000A7 7210                <1> 	jc	short L4
   265                              <1> 		; BL = drive type (for floppy drives)
   266                              <1> 		; DL = number of floppy drives
   267                              <1> 		;		
   268                              <1> 		; ES:DI = Address of DPT from BIOS
   269                              <1> 		;
   270 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   271                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   272                              <1> 	; 14/01/2015
   273 000000AB E8BB01              <1> 	call	set_disk_parms
   274                              <1> 	; 10/12/2014
   275 000000AE 81FE[2C5E]          <1> 	cmp	si, fd0_type
   276 000000B2 7705                <1> 	ja	short L4
   277 000000B4 46                  <1> 	inc	si ; fd1_type
   278 000000B5 B201                <1> 	mov	dl, 1
   279 000000B7 EBE6                <1> 	jmp	short L3
   280                              <1> L4:
   281                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   282 000000B9 B27F                <1> 	mov	dl, 7Fh
   283                              <1> 	; 24/12/2014 (Temporary)
   284 000000BB 803E[2B5E]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   285                              <1> 	;ja	L10       ; yes, all fixed disk operations
   286                              <1> 			  ; will be performed according to
   287                              <1> 			  ; present EDD specification
   288                              <1> 	; 02/01/2022
   289 000000C0 7603                <1> 	jna	short L5
   290 000000C2 E99100              <1> 	jmp	L10
   291                              <1> L5:
   292 000000C5 FEC2                <1> 	inc 	dl
   293 000000C7 8816[295E]          <1>         mov     [drv], dl
   294 000000CB 8816[2A5E]          <1>         mov     [last_drv], dl ; 14/01/2015
   295 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   296 000000D1 CD13                <1> 	int	13h	; (conventional function)
   297                              <1> 	;jc	L13	; fixed disk drive not ready
   298                              <1> 	; 02/01/2022
   299 000000D3 7303                <1> 	jnc	short L6
   300 000000D5 E98301              <1> 	jmp	L13
   301                              <1> L6:
   302 000000D8 8816[2B5E]          <1>         mov     [hdc], dl ; number of drives
   303                              <1> 	;; 14/01/2013
   304                              <1> 	;;push	cx
   305 000000DC E88A01              <1> 	call	set_disk_parms
   306                              <1> 	;;pop	cx
   307                              <1> 	;
   308                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   309 000000DF 8A16[295E]          <1>         mov     dl, [drv]
   310 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   311 000000E6 80FA80              <1> 	cmp	dl, 80h
   312 000000E9 7603                <1> 	jna	short L7
   313 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   314                              <1> L7:	
   315 000000EE 31C0                <1> 	xor	ax, ax
   316 000000F0 8ED8                <1> 	mov	ds, ax
   317 000000F2 8B37                <1>         mov     si, [bx]
   318 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   319 000000F7 8ED8                <1> 	mov	ds, ax
   320 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   321                              <1> 	;jne	L12 ; invalid FDPT
   322                              <1> 	; 02/01/2022
   323 000000FC 7403                <1> 	je	short L7_8
   324 000000FE E95601              <1> 	jmp	L12
   325                              <1> L7_8:
   326 00000101 BF0000              <1> 	mov	di, HD0_DPT
   327 00000104 80FA80              <1> 	cmp	dl, 80h
   328 00000107 7603                <1> 	jna	short L8
   329 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   330                              <1> L8:
   331                              <1> 	; 30/12/2014
   332 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   333 0000010F 8EC0                <1> 	mov	es, ax
   334                              <1> 	; 24/12/2014
   335 00000111 B90800              <1> 	mov	cx, 8
   336 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   337 00000116 8CC8                <1> 	mov	ax, cs
   338 00000118 8ED8                <1> 	mov	ds, ax
   339                              <1> 	; 02/02/2015
   340 0000011A 8A0E[295E]          <1>         mov     cl, [drv]
   341 0000011E 88CB                <1> 	mov	bl, cl
   342 00000120 B8F001              <1> 	mov	ax, 1F0h
   343 00000123 80E301              <1> 	and	bl, 1
   344 00000126 7406                <1> 	jz	short L9
   345 00000128 C0E304              <1> 	shl	bl, 4
   346 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   347                              <1> L9:
   348 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   349 0000012F 050602              <1> 	add	ax, 206h
   350 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   351 00000133 88D8                <1> 	mov	al, bl
   352 00000135 04A0                <1> 	add	al, 0A0h
   353 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   354                              <1> 	;
   355 00000138 FE06[295E]          <1> 	inc	byte [drv]
   356 0000013C BB[AE5D]            <1> 	mov	bx, hd0_type - 80h
   357 0000013F 01CB                <1> 	add	bx, cx
   358 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   359 00000144 A0[2B5E]            <1> 	mov	al, [hdc]
   360 00000147 FEC8                <1> 	dec	al
   361                              <1> 	;jz	L13
   362                              <1> 	; 02/01/2022
   363 00000149 7408                <1> 	jz	short L9_10
   364 0000014B 80FA80              <1> 	cmp	dl, 80h
   365                              <1>         ;jna	L5
   366                              <1> 	;jmp	L13
   367                              <1> 	; 02/01/2022
   368 0000014E 7703                <1> 	ja	short L9_10
   369 00000150 E972FF              <1> 	jmp	L5
   370                              <1> L9_10:
   371 00000153 E90501              <1>         jmp     L13
   372                              <1> L10:
   373 00000156 FEC2                <1> 	inc 	dl
   374                              <1> 	; 25/12/2014
   375 00000158 8816[295E]          <1> 	mov	[drv], dl
   376 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   377 0000015E CD13                <1> 	int	13h	; (conventional function)
   378                              <1> 	;jc	L13
   379                              <1> 	; 02/01/2022
   380 00000160 72F1                <1> 	jc	short L9_10
   381                              <1> 	; 14/01/2015
   382 00000162 8A16[295E]          <1> 	mov	dl, [drv]
   383 00000166 52                  <1> 	push	dx
   384 00000167 51                  <1> 	push	cx
   385 00000168 E8FE00              <1> 	call	set_disk_parms
   386 0000016B 59                  <1> 	pop	cx
   387 0000016C 5A                  <1> 	pop	dx
   388                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   389                              <1> 	; 04/02/2016 (esi -> si)
   390                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   391                              <1> 	;		 ; at the '_end' of kernel.
   392                              <1> 	;mov	word [si], 30
   393                              <1> 	; 06/07/2016
   394 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   395                              <1> 	; 09/07/2016
   396 00000170 B81E00              <1> 	mov	ax, 001Eh
   397 00000173 8824                <1> 	mov	[si], ah ; 0
   398 00000175 46                  <1> 	inc	si
   399 00000176 8904                <1> 	mov	word [si], ax
   400                              <1>  	; word [si] = 30
   401                              <1> 	;
   402 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   403 0000017A CD13                <1> 	int	13h
   404                              <1>         ;jc	L13
   405                              <1> 	; 02/01/2022
   406 0000017C 72D5                <1> 	jc	short L9_10
   407                              <1> 	; 04/02/2016 (ebx -> bx)
   408                              <1> 	; 14/01/2015
   409                              <1> 	;sub	bx, bx
   410 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   411 00000180 88D3                <1> 	mov	bl, dl
   412 00000182 80EB80              <1> 	sub	bl, 80h
   413 00000185 81C3[2E5E]          <1> 	add	bx, hd0_type
   414 00000189 8A07                <1> 	mov 	al, [bx]
   415 0000018B 0C80                <1> 	or	al, 80h
   416 0000018D 8807                <1> 	mov 	[bx], al	
   417 0000018F 81EB[2C5E]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   418 00000193 81C3[4E5E]          <1> 	add	bx, drv.status
   419 00000197 8807                <1> 	mov	[bx], al
   420                              <1> 	; 04/02/2016 (eax -> ax)
   421 00000199 8B4410              <1> 	mov	ax, [si+16]
   422 0000019C 854412              <1> 	test	ax, [si+18]
   423 0000019F 7413                <1> 	jz	short L10_A0h 
   424                              <1> 			; 'CHS only' disks on EDD system 
   425                              <1> 			;  are reported with ZERO disk size
   426 000001A1 81EB[4E5E]          <1> 	sub	bx, drv.status
   427 000001A5 C1E302              <1> 	shl	bx, 2
   428 000001A8 81C3[325E]          <1> 	add	bx, drv.size ; disk size (in sectors)
   429 000001AC 8907                <1> 	mov	[bx], ax
   430 000001AE 8B4412              <1> 	mov	ax, [si+18]
   431                              <1> 	;mov	[bx], ax
   432                              <1> 	; 02/01/2022 (BugFix)
   433 000001B1 894702              <1> 	mov	[bx+2], ax
   434                              <1> 
   435                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   436                              <1> 	 ; for CHS disks (28/02/2015)
   437                              <1> 	; 30/12/2014
   438 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   439 000001B7 88D0                <1> 	mov	al, dl
   440 000001B9 83E003              <1> 	and 	ax, 3
   441 000001BC C0E005              <1> 	shl	al, 5 ; *32
   442 000001BF 01C7                <1> 	add 	di, ax
   443 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   444 000001C4 8EC0                <1> 	mov	es, ax
   445                              <1> 	;
   446 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   447 000001C8 88CC                <1> 	mov	ah, cl	
   448 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   449 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   450 000001CE AB                  <1> 	stosw		
   451 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   452 000001D1 FEC0                <1> 	inc	al
   453 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   454 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   455 000001D6 AA                  <1> 	stosb
   456 000001D7 8A440C              <1> 	mov	al, [si+12]
   457 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   458 000001DB 31C0                <1>  	xor	ax, ax
   459                              <1> 	;dec	ax	 ; 02/01/2015 
   460 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   461                              <1> 	;xor	al, al	 ; 02/01/2015	
   462 000001DE AA                  <1> 	stosb		 ; reserved
   463 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   464                              <1> 		         ; (do not disable retries, 
   465                              <1> 			 ; more than 8 heads)
   466 000001E1 AA                  <1> 	stosb
   467 000001E2 8B4404              <1> 	mov	ax, [si+4]
   468 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   469                              <1> 	;push	ax	 ; 02/01/2015
   470 000001E6 8A4408              <1> 	mov	al, [si+8]
   471 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   472 000001EA 29C0                <1> 	sub 	ax, ax
   473                              <1> 	;pop	ax	 ; 02/01/2015	
   474 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   475 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   476 000001EF 243F                <1> 	and 	al, 3Fh	
   477 000001F1 AA                  <1> 	stosb
   478                              <1> 	;sub	al, al	 ; checksum
   479                              <1> 	;stosb
   480                              <1> 	;
   481 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   482 000001F5 AD                  <1> 	lodsw
   483 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   484 000001F7 AD                  <1> 	lodsw
   485 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   486                              <1> 	;
   487                              <1> 	; checksum calculation
   488 000001F9 89FE                <1> 	mov	si, di
   489 000001FB 06                  <1> 	push	es
   490 000001FC 1F                  <1> 	pop	ds
   491                              <1> 	;mov	cx, 16
   492 000001FD B90F00              <1> 	mov 	cx, 15
   493 00000200 29CE                <1> 	sub	si, cx
   494 00000202 30E4                <1> 	xor	ah, ah
   495                              <1> 	;del	cl
   496                              <1> L11:		
   497 00000204 AC                  <1> 	lodsb
   498 00000205 00C4                <1> 	add	ah, al
   499 00000207 E2FB                <1> 	loop	L11
   500                              <1> 	;
   501 00000209 88E0                <1> 	mov	al, ah
   502 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   503 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   504                              <1> 	;
   505 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   506 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   507                              <1> 	;
   508                              <1> 	; 23/02/2015
   509 00000210 57                  <1> 	push	di
   510                              <1> 	; ES:DI points to DPTE (FDPTE) location
   511                              <1> 	;mov	cx, 8
   512 00000211 B108                <1> 	mov	cl, 8
   513 00000213 F3A5                <1> 	rep	movsw	
   514                              <1> 	;
   515                              <1> 	; 23/02/2015
   516                              <1> 	; (P)ATA drive and LBA validation
   517                              <1> 	; (invalidating SATA drives and setting
   518                              <1> 	; CHS type I/O for old type fixed disks)
   519 00000215 5B                  <1> 	pop	bx
   520 00000216 8CC8                <1> 	mov	ax, cs
   521 00000218 8ED8                <1> 	mov	ds, ax
   522 0000021A 268B07              <1> 	mov	ax, [es:bx]
   523 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   524 00000220 7418                <1> 	je	short L11a
   525 00000222 3D7001              <1> 	cmp	ax, 170h
   526 00000225 7413                <1> 	je	short L11a
   527                              <1> 	; invalidation 
   528                              <1> 	; (because base port address is not 1F0h or 170h)
   529 00000227 30FF                <1> 	xor	bh, bh
   530 00000229 88D3                <1> 	mov	bl, dl
   531 0000022B 80EB80              <1> 	sub	bl, 80h
   532 0000022E C687[2E5E]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   533 00000233 808F[505E]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   534 00000238 EB14                <1> 	jmp	short L11b
   535                              <1> L11a:	
   536                              <1> 	; LBA validation
   537 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   538 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   539 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   540                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   541 00000242 28FF                <1> 	sub	bh, bh
   542 00000244 88D3                <1> 	mov	bl, dl
   543 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   544 00000249 80A7[505E]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   545                              <1> 				; bit 0 = LBA ready bit
   546                              <1> 	; 'diskio' procedure will check this bit !
   547                              <1> L11b:
   548 0000024E 3A16[2A5E]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   549 00000252 7307                <1>         jnb     short L13
   550 00000254 E9FFFE              <1>         jmp     L10
   551                              <1> L12:
   552                              <1> 	; Restore data registers
   553 00000257 8CC8                <1> 	mov	ax, cs
   554 00000259 8ED8                <1> 	mov	ds, ax	
   555                              <1> L13:
   556                              <1> 	; 13/12/2014
   557 0000025B 0E                  <1> 	push	cs
   558 0000025C 07                  <1> 	pop	es
   559                              <1> L14:
   560 0000025D B411                <1> 	mov 	ah, 11h
   561 0000025F CD16                <1> 	int 	16h
   562                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   563                              <1> 	; 02/01/2022
   564 00000261 7447                <1> 	jz	short L16
   565 00000263 B010                <1> 	mov	al, 10h
   566 00000265 CD16                <1> 	int 	16h
   567 00000267 EBF4                <1> 	jmp 	short L14
   568                              <1> L15:
   569                              <1> 
   570                              <1> ; //////
   571                              <1> 
   572                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   573                              <1> %if 0
   574                              <1> 	; 24/11/2014
   575                              <1> 	; 19/11/2014
   576                              <1> 	; 14/11/2014
   577                              <1> 	; Temporary code for disk searching code check
   578                              <1> 	;
   579                              <1> 	; This code will show existing (usable) drives and also
   580                              <1> 	; will show EDD interface support status for hard disks		
   581                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   582                              <1> 	; no need to get it again in protected mode...) 
   583                              <1> 	;	
   584                              <1> 	; 13/11/2014
   585                              <1> 	mov	bx, 7
   586                              <1> 	mov	ah, 0Eh
   587                              <1> 	mov	al, [fd0_type]
   588                              <1> 	and	al, al
   589                              <1> 	jz	short L15a
   590                              <1> 	mov	dl, al
   591                              <1> 	mov	al, 'F'
   592                              <1> 	int 	10h
   593                              <1> 	mov	al, 'D'
   594                              <1> 	int 	10h
   595                              <1> 	mov	al, '0'
   596                              <1> 	int 	10h
   597                              <1> 	mov	al, ' '
   598                              <1> 	int	10h
   599                              <1> 	call	L15c
   600                              <1> 	mov	al, ' '
   601                              <1> 	int	10h
   602                              <1> 	;
   603                              <1> 	mov	al, [fd1_type]
   604                              <1> 	and	al, al
   605                              <1> 	jz	short L15a
   606                              <1> 	mov	dl, al
   607                              <1> 	mov	al, 'F'
   608                              <1> 	int 	10h
   609                              <1> 	mov	al, 'D'
   610                              <1> 	int 	10h
   611                              <1> 	mov	al, '1'
   612                              <1> 	int 	10h
   613                              <1> 	mov	al, ' '
   614                              <1> 	int	10h
   615                              <1> 	call	L15c
   616                              <1> 	mov	al, ' '
   617                              <1> 	int	10h
   618                              <1> 	mov	al, ' '
   619                              <1> 	int	10h
   620                              <1> L15a:
   621                              <1> 	mov	al, [hd0_type]
   622                              <1> 	and	al, al
   623                              <1> 	jz	short L15b
   624                              <1> 	mov	dl, al
   625                              <1> 	mov	al, 'H'
   626                              <1> 	int 	10h
   627                              <1> 	mov	al, 'D'
   628                              <1> 	int 	10h
   629                              <1> 	mov	al, '0'
   630                              <1> 	int 	10h
   631                              <1> 	mov	al, ' '
   632                              <1> 	int 	10h
   633                              <1> 	call	L15c
   634                              <1> 	mov	al, ' '
   635                              <1> 	int	10h
   636                              <1> 	;
   637                              <1> 	mov	al, [hd1_type]
   638                              <1> 	and	al, al
   639                              <1> 	jz	short L15b
   640                              <1> 	mov	dl, al
   641                              <1> 	mov	al, 'H'
   642                              <1> 	int 	10h
   643                              <1> 	mov	al, 'D'
   644                              <1> 	int 	10h
   645                              <1> 	mov	al, '1'
   646                              <1> 	int 	10h
   647                              <1> 	mov	al, ' '
   648                              <1> 	int 	10h
   649                              <1> 	call	L15c
   650                              <1> 	mov	al, ' '
   651                              <1> 	int	10h
   652                              <1> 	;
   653                              <1> 	mov	al, [hd2_type]
   654                              <1> 	and	al, al
   655                              <1> 	jz	short L15b
   656                              <1> 	mov	dl, al
   657                              <1> 	mov	al, 'H'
   658                              <1> 	int 	10h
   659                              <1> 	mov	al, 'D'
   660                              <1> 	int 	10h
   661                              <1> 	mov	al, '2'
   662                              <1> 	int 	10h
   663                              <1> 	mov	al, ' '
   664                              <1> 	int 	10h
   665                              <1> 	call	L15c
   666                              <1> 	mov	al, ' '
   667                              <1> 	int	10h
   668                              <1> 	;
   669                              <1> 	mov	al, [hd3_type]
   670                              <1> 	and	al, al
   671                              <1> 	jz	short L15b
   672                              <1> 	mov	dl, al
   673                              <1> 	mov	al, 'H'
   674                              <1> 	int 	10h
   675                              <1> 	mov	al, 'D'
   676                              <1> 	int 	10h
   677                              <1> 	mov	al, '3'
   678                              <1> 	int 	10h
   679                              <1> 	mov	al, ' '
   680                              <1> 	int 	10h
   681                              <1> 	call	L15c
   682                              <1> 	mov	al, ' '
   683                              <1> 	int	10h
   684                              <1> 	;
   685                              <1> L15b:
   686                              <1> 	mov	al, 0Dh
   687                              <1> 	int 	10h	
   688                              <1> 	mov	al, 0Ah
   689                              <1> 	int 	10h
   690                              <1> 	;;xor	ah, ah
   691                              <1> 	;;int 	16h	
   692                              <1> 	;
   693                              <1>         ;jmp	L16  ; jmp short L16
   694                              <1>         ; 02/01/2022
   695                              <1> 	jmp	short L16
   696                              <1> 	;
   697                              <1> L15c:
   698                              <1> 	mov	dh, dl
   699                              <1> 	shr	dh, 4
   700                              <1> 	add	dh, 30h
   701                              <1> 	and	dl, 15
   702                              <1> 	add	dl, 30h
   703                              <1> 	mov	al, dh
   704                              <1> 	int	10h
   705                              <1> 	mov	al, dl
   706                              <1> 	int	10h
   707                              <1> 	retn
   708                              <1> 	;
   709                              <1> 	; end of temporary code for disk searching code check
   710                              <1> 
   711                              <1> %endif
   712                              <1> 
   713                              <1> ; //////
   714                              <1> 
   715                              <1> set_disk_parms:
   716                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
   717                              <1> 	; 09/05/2022
   718                              <1> 	;	disksize = cylinders*spt*heads (*)
   719                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   720                              <1> 	;
   721                              <1> 	; 04/02/2016 (ebx -> bx)
   722                              <1> 	; 10/07/2015
   723                              <1> 	; 14/01/2015
   724                              <1> 	;push	bx
   725 00000269 28FF                <1> 	sub	bh, bh
   726 0000026B 8A1E[295E]          <1> 	mov	bl, [drv]
   727 0000026F 80FB80              <1> 	cmp	bl, 80h
   728 00000272 7203                <1> 	jb	short sdp0
   729 00000274 80EB7E              <1> 	sub	bl, 7Eh
   730                              <1> sdp0:	
   731 00000277 81C3[4E5E]          <1> 	add	bx, drv.status
   732 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   733                              <1> 	;
   734 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   735 00000280 88CC                <1> 	mov	ah, cl ; 
   736 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   737 00000285 81EB[4E5E]          <1> 	sub	bx, drv.status
   738 00000289 D0E3                <1> 	shl	bl, 1
   739                              <1> 	; 12/07/2022
   740                              <1> 	;add	bx, drv.cylinders
   741 0000028B 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   742                              <1> 	;mov	[bx], ax
   743 0000028C 50                  <1> 	push	ax ; ** cylinders
   744                              <1> 	;sub	bx, drv.cylinders
   745                              <1> 	;add	bx, drv.heads
   746 0000028D 30E4                <1> 	xor	ah, ah
   747 0000028F 88F0                <1> 	mov	al, dh ; heads
   748 00000291 40                  <1> 	inc	ax
   749                              <1> 	;mov	[bx], ax
   750                              <1>         ;sub	bx, drv.heads
   751                              <1>         ;add	bx, drv.spt
   752 00000292 30ED                <1> 	xor	ch, ch
   753 00000294 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   754                              <1> 	;mov	[bx], cx
   755                              <1>         ;sub	bx, drv.spt
   756 00000297 D1E3                <1> 	shl	bx, 1
   757 00000299 81C3[325E]          <1> 	add	bx, drv.size ; disk size (in sectors)
   758                              <1> 	; LBA size = cylinders * heads * secpertrack
   759 0000029D F7E1                <1> 	mul	cx 
   760 0000029F 89C2                <1> 	mov	dx, ax	; heads*spt					
   761 000002A1 58                  <1> 	pop	ax ; ** cylinders
   762                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   763                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   764 000002A2 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   765 000002A4 8907                <1> 	mov	[bx], ax
   766 000002A6 895702              <1> 	mov	[bx+2], dx
   767                              <1> 	;
   768                              <1> 	;pop	bx
   769 000002A9 C3                  <1> 	retn
   770                              <1> 
   771                              <1> ;align 2
   772                              <1> 
   773                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   774                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   775                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   776                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   777                              <1> 
   778                              <1> ;last_drv:
   779                              <1> ;	db  0
   780                              <1> ;drv_status:
   781                              <1> ;	db  0,0,0,0,0,0
   782                              <1> ;	db 0
   783                              <1> 
   784                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   785                              <1> 
   786                              <1> L16:
   212                                  
   213                                  	; 10/11/2014
   214 000002AA FA                           	cli	; Disable interrupts (clear interrupt flag)
   215                                  		; Reset Interrupt MASK Registers (Master&Slave)
   216                                  	;mov	al, 0FFh	; mask off all interrupts
   217                                  	;out	21h, al		; on master PIC (8259)
   218                                  	;jmp 	$+2  ; (delay)
   219                                  	;out	0A1h, al	; on slave PIC (8259)
   220                                  	;
   221                                  	; Disable NMI 
   222 000002AB B080                    	mov   	al, 80h 
   223 000002AD E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   224                                  	; 23/02/2015
   225 000002AF 90                      	nop			;
   226                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   227                                  				; for preventing unknown state (!?)
   228                                  	;
   229                                   	; 20/08/2014
   230                                  	; Moving the kernel 64 KB back (to physical address 0)
   231                                  	; DS = CS = 1000h
   232                                  	; 05/11/2014
   233 000002B0 31C0                    	xor	ax, ax
   234 000002B2 8EC0                    	mov	es, ax ; ES = 0
   235                                  	;
   236 000002B4 B90040                  	mov	cx, (KEND - KLOAD)/4
   237 000002B7 31F6                    	xor	si, si
   238 000002B9 31FF                    	xor	di, di
   239 000002BB F366A5                  	rep	movsd
   240                                  	;
   241 000002BE 06                      	push	es ; 0
   242 000002BF 68[C302]                	push	L17
   243 000002C2 CB                      	retf
   244                                  	;
   245                                  L17:
   246                                  	; Turn off the floppy drive motor
   247 000002C3 BAF203                          mov     dx, 3F2h
   248 000002C6 EE                              out     dx, al ; 0 ; 31/12/2013
   249                                  
   250                                  	; Enable access to memory above one megabyte
   251                                  L18:
   252 000002C7 E464                    	in	al, 64h
   253 000002C9 A802                    	test	al, 2
   254 000002CB 75FA                            jnz     short L18
   255 000002CD B0D1                    	mov	al, 0D1h	; Write output port
   256 000002CF E664                    	out	64h, al
   257                                  L19:
   258 000002D1 E464                    	in	al, 64h
   259 000002D3 A802                    	test	al, 2
   260 000002D5 75FA                            jnz     short L19
   261 000002D7 B0DF                    	mov	al, 0DFh	; Enable A20 line
   262 000002D9 E660                    	out	60h, al
   263                                  ;L20:
   264                                  	;
   265                                  	; Load global descriptor table register
   266                                  
   267                                          ;mov     ax, cs
   268                                          ;mov     ds, ax
   269                                  
   270 000002DB 2E0F0116[505B]                  lgdt    [cs:gdtd]
   271                                  
   272 000002E1 0F20C0                          mov     eax, cr0
   273                                  	; or 	eax, 1
   274 000002E4 40                      	inc     ax
   275 000002E5 0F22C0                  	mov     cr0, eax
   276                                  
   277                                  	; Jump to 32 bit code
   278                                  	
   279 000002E8 66                      	db 66h 			; Prefix for 32-bit
   280 000002E9 EA                      	db 0EAh 		; Opcode for far jump
   281 000002EA [F0020000]              	dd StartPM 		; Offset to start, 32-bit
   282                                  				; (1000h:StartPM = StartPM + 10000h)
   283 000002EE 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   284                                  				; assuming that StartPM resides in code32
   285                                  
   286                                  [BITS 32] 
   287                                  
   288                                  StartPM:
   289                                  	; Kernel Base Address = 0 ; 30/12/2013
   290 000002F0 66B81000                	mov ax, KDATA           ; Save data segment identifier
   291 000002F4 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   292 000002F6 8EC0                           	mov es, ax              ; Move data segment into ES register
   293 000002F8 8EE0                           	mov fs, ax              ; Move data segment into FS register
   294 000002FA 8EE8                          	mov gs, ax              ; Move data segment into GS register
   295 000002FC 8ED0                            mov ss, ax              ; Move data segment into SS register
   296 000002FE BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   297                                  
   298                                  clear_bss: ; Clear uninitialized data area
   299                                  	; 11/03/2015
   300 00000303 31C0                    	xor	eax, eax ; 0
   301                                  	;mov	ecx, (bss_end - bss_start)/4
   302                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   303                                  	; 27/02/2022
   304 00000305 B9BA050000              	mov	ecx, BSS_SIZE/4
   305 0000030A BF[A0600000]            	mov	edi, bss_start
   306 0000030F F3AB                    	rep	stosd  	
   307                                  
   308                                  memory_init:
   309                                  	; Initialize memory allocation table and page tables
   310                                  	; 16/11/2014
   311                                  	; 15/11/2014
   312                                  	; 07/11/2014
   313                                  	; 06/11/2014
   314                                  	; 05/11/2014
   315                                  	; 04/11/2014
   316                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   317                                  	;
   318                                  ;	xor	eax, eax
   319                                  ;	xor 	ecx, ecx
   320 00000311 B108                    	mov	cl, 8
   321 00000313 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   322 00000318 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   323                                  				   ; for the first 1 MB memory
   324                                  	;
   325 0000031A 668B0D[92600000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   326                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   327 00000321 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   328 00000325 890D[10630000]          	mov	[free_pages], ecx
   329 0000032B 668B15[94600000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   330                                  				   ; between 16 MB and 4 GB.	
   331 00000332 6609D2                  	or	dx, dx
   332 00000335 7413                    	jz	short mi_0
   333                                  	;
   334 00000337 6689D0                  	mov	ax, dx
   335 0000033A C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   336 0000033D 0105[10630000]          	add	[free_pages], eax
   337 00000343 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   338 00000348 EB07                    	jmp	short mi_1
   339                                  mi_0:
   340 0000034A 6689C8                  	mov	ax, cx
   341 0000034D 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   342                                  mi_1:
   343 00000351 A3[0C630000]            	mov	[memory_size], eax ; Total available memory in pages
   344                                  				   ; 1 alloc. tbl. bit = 1 memory page
   345                                  				   ; 32 allocation bits = 32 mem. pages   
   346                                  	;
   347 00000356 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   348 0000035B C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   349                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   350                                  				   ;  --> x M.A.T. pages, if y = 0
   351 0000035E 66A3[20630000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   352 00000364 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   353                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   354 00000367 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   355                                  	; Set/Calculate Kernel's Page Directory Address
   356 00000369 81C300001000            	add	ebx, MEM_ALLOC_TBL
   357 0000036F 891D[08630000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   358                                  				   ; just after the last M.A.T. page
   359                                  	;
   360 00000375 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   361 00000378 A3[18630000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   362                                  	;			   ; (allocation status search must be 
   363                                  				   ; stopped after here)	
   364 0000037D 31C0                    	xor	eax, eax
   365 0000037F 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   366 00000380 6651                    	push	cx
   367 00000382 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   368                                  				   ; count of 32 allocation bits
   369 00000385 F3AB                    	rep	stosd
   370 00000387 6659                    	pop	cx
   371 00000389 40                      	inc	eax		   ; 0	
   372 0000038A 80E11F                  	and	cl, 31		   ; remain bits
   373 0000038D 7412                    	jz	short mi_4
   374 0000038F 8907                    	mov	[edi], eax	   ; reset	
   375                                  mi_2:
   376 00000391 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   377 00000394 FEC9                    	dec	cl
   378 00000396 7404                    	jz	short mi_3
   379 00000398 FEC0                    	inc	al
   380 0000039A EBF5                    	jmp	short mi_2
   381                                  mi_3:
   382 0000039C 28C0                    	sub	al, al	   	   ; 0
   383 0000039E 83C704                  	add	edi, 4		   ; 15/11/2014
   384                                  mi_4:
   385 000003A1 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   386 000003A4 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   387                                  	;	
   388 000003A6 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   389                                  	;	
   390 000003AB 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   391 000003AD 7406                    	jz	short mi_5	  ; jump if EDI points to 
   392                                  				  ;         end of first 16 MB	
   393 000003AF D1E9                    	shr	ecx, 1		  ; convert to dword count
   394 000003B1 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   395 000003B3 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   396                                  				  ; (memory hole under 16 MB)
   397                                  mi_5:
   398 000003B5 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   399 000003B8 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   400 000003BA 9C                      	pushf			  ; 16/11/2014		
   401 000003BB 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   402 000003BC F3AB                    	rep	stosd
   403 000003BE 40                      	inc	eax		  ; 0
   404 000003BF 9D                      	popf			  ; 16/11/2014
   405 000003C0 7305                    	jnc	short mi_6
   406 000003C2 6648                    	dec	ax		  ; eax = 0000FFFFh
   407 000003C4 AB                      	stosd
   408 000003C5 6640                    	inc	ax		  ; 0		
   409                                  mi_6:
   410 000003C7 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   411 000003C9 730A                    	jnb	short mi_7	  ; end of memory allocation table
   412                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   413 000003CB 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   414 000003CD 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   415 000003CF D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   416 000003D1 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   417 000003D3 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   418                                  mi_7:
   419                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   420 000003D5 BA00001000              	mov	edx, MEM_ALLOC_TBL
   421                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   422                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   423 000003DA 668B0D[20630000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   424 000003E1 89D7                    	mov	edi, edx
   425 000003E3 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   426                                  				  ; byte offset in M.A.T.
   427                                  				  ; (1 M.A.T. byte points to 
   428                                  				  ;	      32768 bytes)
   429                                  				  ; Note: MEM_ALLOC_TBL address 
   430                                  				  ; must be aligned on 128 KB 
   431                                  				  ; boundary!
   432 000003E6 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   433                                  	; eax = 0
   434 000003E8 290D[10630000]          	sub	[free_pages], ecx ; 07/11/2014
   435                                  mi_8:
   436 000003EE 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   437                                  	;dec	bl
   438 000003F1 FEC9                    	dec	cl
   439 000003F3 7404                    	jz	short mi_9
   440 000003F5 FEC0                    	inc	al
   441 000003F7 EBF5                    	jmp	short mi_8
   442                                  mi_9:
   443                                  	;
   444                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   445                                  	;		(allocate pages for system page tables)
   446                                  
   447                                  	; edx = MEM_ALLOC_TBL
   448 000003F9 8B0D[0C630000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   449 000003FF 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   450 00000405 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   451                                  				 ; page table count (PDE count)
   452                                  	;
   453 00000408 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   454                                  	;
   455 00000409 41                      	inc	ecx		 ; +1 for kernel page directory	
   456                                  	;
   457 0000040A 290D[10630000]          	sub	[free_pages], ecx ; 07/11/2014
   458                                  	;
   459 00000410 8B35[08630000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   460 00000416 C1EE0C                  	shr	esi, 12		 ; convert to page number
   461                                  mi_10:
   462 00000419 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   463 0000041B 89C3                    	mov	ebx, eax
   464 0000041D C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   465 00000420 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   466                                  				 ;   to align on dword boundary
   467 00000423 83E01F                  	and	eax, 31		 ; set allocation bit position 
   468                                  				 ;  (bit 0 to bit 31)
   469                                  	;
   470 00000426 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   471                                  	;
   472 00000428 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   473                                  	;
   474 0000042B 46                      	inc	esi		 ; next page table
   475 0000042C E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   476                                  				 ; (ecx = page table count + 1)		
   477                                  	;
   478 0000042E 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   479                                  	;
   480                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   481                                  	;
   482                                  	; Initialize Kernel's Page Directory
   483 0000042F 8B3D[08630000]          	mov	edi, [k_page_dir]
   484 00000435 89F8                    	mov	eax, edi
   485 00000437 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   486                                  		     	      ; supervisor + read&write + present
   487 00000439 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   488                                  mi_11:
   489 0000043B 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   490                                  			        ; EAX points to next page table
   491 00000440 AB                      	stosd
   492 00000441 E2F8                    	loop	mi_11
   493 00000443 29C0                    	sub	eax, eax	; Empty PDE
   494 00000445 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   495 00000449 29D1                    	sub	ecx, edx
   496 0000044B 7402                    	jz	short mi_12
   497 0000044D F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   498                                  	;
   499                                  	; Initialization of Kernel's Page Directory is OK, here.
   500                                  mi_12:
   501                                  	; Initialize Kernel's Page Tables
   502                                  	;
   503                                  	; (EDI points to address of page table 0)
   504                                  	; eax = 0
   505 0000044F 8B0D[0C630000]          	mov	ecx, [memory_size] ; memory size in pages
   506 00000455 89CA                    	mov	edx, ecx	; (***)
   507 00000457 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   508                                  			     ; supervisor + read&write + present 	
   509                                  mi_13:
   510 00000459 AB                      	stosd
   511 0000045A 0500100000              	add	eax, 4096	
   512 0000045F E2F8                    	loop	mi_13	
   513 00000461 6681E2FF03              	and	dx, 1023	; (***)
   514 00000466 740B                    	jz	short mi_14
   515 00000468 66B90004                	mov	cx, 1024	
   516 0000046C 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   517 0000046F 31C0                    	xor	eax, eax
   518 00000471 F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   519                                  				; of the last page table
   520                                  mi_14:
   521                                  	;  Initialization of Kernel's Page Tables is OK, here.
   522                                  	;
   523 00000473 89F8                    	mov	eax, edi	; end of the last page table page
   524                                  			        ; (beginging of user space pages)
   525 00000475 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   526 00000478 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   527                                  				; aligning on dword boundary	
   528                                  	 
   529 0000047A A3[1C630000]            	mov	[first_page], eax
   530 0000047F A3[14630000]            	mov	[next_page], eax ; The first free page pointer
   531                                  				 ; for user programs
   532                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   533                                  	;
   534                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   535                                  	;
   536                                  	
   537                                  	; Enable paging
   538                                  	;
   539 00000484 A1[08630000]                    mov     eax, [k_page_dir]
   540 00000489 0F22D8                  	mov	cr3, eax
   541 0000048C 0F20C0                  	mov	eax, cr0
   542 0000048F 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   543 00000494 0F22C0                  	mov	cr0, eax
   544                                          ;jmp    KCODE:StartPMP
   545                                  
   546 00000497 EA                      	db 0EAh 		; Opcode for far jump
   547 00000498 [9E040000]                      dd StartPMP		; 32 bit offset
   548 0000049C 0800                    	dw KCODE		; kernel code segment descriptor
   549                                  
   550                                  
   551                                  StartPMP:
   552                                  	; 06/11//2014
   553                                  	; Clear video page 0
   554                                  	;
   555                                  	; Temporary Code
   556                                  	;
   557 0000049E B9E8030000              	mov	ecx, 80*25/2
   558 000004A3 BF00800B00              	mov	edi, 0B8000h
   559 000004A8 31C0                    	xor	eax, eax	; black background, black fore color
   560 000004AA F3AB                    	rep	stosd
   561                                  	
   562                                  	; 19/08/2014
   563                                  	; Kernel Base Address = 0
   564                                  	; It is mapped to (physically) 0 in the page table.
   565                                  	; So, here is exactly 'StartPMP' address.
   566                                  	;
   567                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   568                                  	;;mov	esi, msgPM
   569                                  	;; 14/08/2015 (kernel version message will appear
   570                                  	;;	       when protected mode and paging is enabled)
   571 000004AC B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   572 000004AE BE[645E0000]            	mov	esi, msgKVER
   573 000004B3 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   574                                  	; 20/08/2014
   575 000004B8 E892010000              	call	printk
   576                                  
   577                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   578                                  	; // Set IRQ offsets
   579                                  	;
   580                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   581                                  	;
   582                                  					;; ICW1
   583 000004BD B011                    	mov	al, 11h			; Initialization sequence
   584 000004BF E620                    	out	20h, al			; 	8259A-1
   585                                  	; jmp 	$+2
   586 000004C1 E6A0                    	out	0A0h, al		; 	8259A-2
   587                                  					;; ICW2
   588 000004C3 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   589 000004C5 E621                    	out	21h, al			;	for 8259A-1
   590                                  	; jmp 	$+2
   591 000004C7 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   592 000004C9 E6A1                    	out	0A1h, al		; 	for 8259A-2
   593                                  					;
   594 000004CB B004                    	mov	al, 04h			;; ICW3
   595 000004CD E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   596                                  	; jmp 	$+2
   597 000004CF B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   598 000004D1 E6A1                    	out	0A1h, al		;
   599                                  					;; ICW4
   600 000004D3 B001                    	mov	al, 01h	 		;
   601 000004D5 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   602                                  	; jmp 	$+2
   603 000004D7 E6A1                    	out	0A1h, al		;	for both chips.
   604                                  
   605                                  	;mov	al, 0FFh	; mask off all interrupts for now
   606                                  	;out	21h, al
   607                                  	;; jmp 	$+2
   608                                  	;out	0A1h, al
   609                                  
   610                                  	; 02/04/2015
   611                                  	; 26/03/2015 System call (INT 30h) modification
   612                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   613                                  	;
   614                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   615                                  	;  setup_idt:
   616                                  	;
   617                                          ;; 16/02/2015
   618                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   619                                  	; 21/08/2014 (timer_int)
   620 000004D9 BE[5C5B0000]            	mov	esi, ilist
   621 000004DE 8D3D[A0600000]          	lea	edi, [idt]
   622                                  	; 26/03/2015
   623 000004E4 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   624                                  	; 02/04/2015
   625 000004E9 BB00000800              	mov	ebx, 80000h
   626                                  rp_sidt1:
   627 000004EE AD                      	lodsd
   628 000004EF 89C2                    	mov	edx, eax
   629 000004F1 66BA008E                	mov	dx, 8E00h
   630 000004F5 6689C3                  	mov	bx, ax
   631 000004F8 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   632                                         			        ; /* interrupt gate - dpl=0, present */
   633 000004FA AB                      	stosd	; selector & offset bits 0-15 	
   634 000004FB 89D0                    	mov	eax, edx
   635 000004FD AB                      	stosd	; attributes & offset bits 16-23
   636 000004FE E2EE                    	loop	rp_sidt1
   637 00000500 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   638                                  rp_sidt2:
   639 00000502 AD                      	lodsd
   640 00000503 21C0                    	and	eax, eax
   641 00000505 7413                    	jz	short rp_sidt3
   642 00000507 89C2                    	mov	edx, eax
   643 00000509 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   644 0000050D 6689C3                  	mov	bx, ax
   645 00000510 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   646 00000512 AB                      	stosd
   647 00000513 89D0                    	mov	eax, edx
   648 00000515 AB                      	stosd
   649 00000516 E2EA                    	loop	rp_sidt2
   650 00000518 EB16                    	jmp	short sidt_OK
   651                                  rp_sidt3:
   652 0000051A B8[72090000]            	mov	eax, ignore_int
   653 0000051F 89C2                    	mov	edx, eax
   654 00000521 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   655 00000525 6689C3                  	mov	bx, ax
   656 00000528 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   657                                  rp_sidt4:
   658 0000052A AB                      	stosd
   659 0000052B 92                      	xchg	eax, edx
   660 0000052C AB                      	stosd
   661 0000052D 92                      	xchg	edx, eax
   662 0000052E E2FA                    	loop	rp_sidt4
   663                                  sidt_OK: 
   664 00000530 0F011D[565B0000]        	lidt 	[idtd]
   665                                  	;
   666                                  	; TSS descriptor setup ; 24/03/2015
   667 00000537 B8[A0620000]            	mov	eax, task_state_segment
   668 0000053C 66A3[4A5B0000]          	mov	[gdt_tss0], ax
   669 00000542 C1C010                  	rol	eax, 16
   670 00000545 A2[4C5B0000]            	mov	[gdt_tss1], al
   671 0000054A 8825[4F5B0000]          	mov	[gdt_tss2], ah
   672 00000550 66C705[06630000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   672 00000558 00                 
   673                                  		; 
   674                                  		; IO Map Base address (When this address points
   675                                  		; to end of the TSS, CPU does not use IO port 
   676                                  		; permission bit map for RING 3 IO permissions, 
   677                                  		; access to any IO ports in ring 3 will be forbidden.)
   678                                   		;
   679                                  	;mov	[tss.esp0], esp ; TSS offset 4
   680                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   681 00000559 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   682                                  			 ; occurs (or a system call -software INT- is requested)
   683                                  			 ; while cpu running in ring 3 (in user mode).				
   684                                  			 ; (Kernel stack pointer and segment will be loaded
   685                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   686 0000055D 0F00D8                  	ltr	ax  ; Load task register
   687                                  	;
   688                                  esp0_set0:
   689                                  	; 30/07/2015
   690 00000560 8B0D[0C630000]          	mov 	ecx, [memory_size] ; memory size in pages
   691 00000566 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   692 00000569 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   693                                  			  ; (kernel mode virtual address)
   694 0000056F 7605                    	jna	short esp0_set1
   695                                  	;
   696                                  	; If available memory > CORE (end of the 1st 4 MB)
   697                                  	; set stack pointer to CORE
   698                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   699                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   700 00000571 B900004000              	mov	ecx, CORE
   701                                  esp0_set1:
   702 00000576 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   703                                  esp0_set_ok:
   704                                  	; 30/07/2015 (**tss.esp0**) 
   705 00000578 8925[A4620000]          	mov	[tss.esp0], esp
   706 0000057E 66C705[A8620000]10-             mov     word [tss.ss0], KDATA
   706 00000586 00                 
   707                                  	; 14/08/2015
   708                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   709                                  	;
   710                                  	;cli	; Disable interrupts (for CPU)
   711                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   712                                  	;
   713 00000587 30C0                    	xor	al, al		; Enable all hardware interrupts!
   714 00000589 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   715 0000058B EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   716 0000058D E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   717                                  				; (Even if related hardware component
   718                                  				;  does not exist!)
   719                                  	; Enable NMI 
   720 0000058F B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   721 00000591 E670                    	out  	70h, al
   722                                  	; 23/02/2015
   723 00000593 90                      	nop
   724 00000594 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   725                                  				; for preventing unknown state (!?)
   726                                  	;
   727                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   728                                  	;
   729                                  	; 02/09/2014
   730                                  	;xor	bx, bx
   731                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   732                                  	; 27/02/2022	
   733 00000596 31DB                    	xor	ebx, ebx
   734 00000598 31D2                    	xor	edx, edx
   735 0000059A B602                    	mov	dh, 2
   736 0000059C E8250F0000              	call	set_cpos
   737                                  	;
   738                                  	; 06/11/2014
   739                                  	; Temporary Code
   740                                  	;
   741 000005A1 E89A100000              	call	memory_info
   742                                  	; 14/08/2015
   743                                  	;call getch ; 28/02/2015
   744                                  drv_init:
   745 000005A6 FB                      	sti	; Enable Interrupts 
   746                                  	; 06/02/2015
   747 000005A7 8B15[2E5E0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   748 000005AD 668B1D[2C5E0000]        	mov	bx, [fd0_type] ; fd0, fd1
   749                                  	; 22/02/2015
   750 000005B4 6621DB                  	and	bx, bx
   751 000005B7 751B                    	jnz	short di1
   752                                  	;
   753 000005B9 09D2                    	or 	edx, edx
   754 000005BB 7529                    	jnz	short di2
   755                                  	;
   756                                  setup_error:
   757 000005BD BE[4B5F0000]            	mov 	esi, setup_error_msg
   758                                  psem:	
   759 000005C2 AC                      	lodsb
   760 000005C3 08C0                    	or	al, al
   761                                  	;jz	short haltx ; 22/02/2015
   762 000005C5 7426                    	jz	short di3
   763 000005C7 56                      	push	esi
   764 000005C8 31DB                    	xor	ebx, ebx ; 0
   765                                  			; Video page 0 (bl=0)
   766 000005CA B407                    	mov	ah, 07h ; Black background, 
   767                                  			; light gray forecolor
   768 000005CC E8EB0D0000              	call	write_tty
   769 000005D1 5E                      	pop	esi
   770 000005D2 EBEE                    	jmp	short psem
   771                                  
   772                                  di1:
   773                                  	; supress 'jmp short T6'
   774                                  	;  (activate fdc motor control code)
   775 000005D4 66C705[D0060000]90-     	mov	word [T5], 9090h ; nop
   775 000005DC 90                 
   776                                  	;
   777                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   778                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   779                                  	;stosw
   780                                  	;mov 	ax, cs
   781                                  	;stosw
   782                                  	;; 16/02/2015
   783                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   784                                  	;
   785 000005DD E82A1A0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   786                                  	;
   787 000005E2 09D2                    	or	edx, edx
   788 000005E4 7407                            jz      short di3
   789                                  di2:
   790 000005E6 E8531A0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   791 000005EB 72D0                            jc      short setup_error
   792                                  di3:
   793 000005ED E822100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   794                                  	;
   795 000005F2 E87D540000              	call	display_disks ; 07/03/2015  (Temporary)
   796                                  ;haltx:
   797                                  	; 14/08/2015
   798                                  	;call	getch ; 22/02/2015
   799 000005F7 FB                      	sti	; Enable interrupts (for CPU)
   800                                  	; 14/08/2015
   801                                  	;mov 	ecx, 0FFFFFFFh
   802                                  	; 16/02/2022
   803 000005F8 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   804                                  md_info_msg_wait:
   805 000005FD 51                      	push 	ecx
   806 000005FE B001                    	mov	al, 1
   807 00000600 8A25[36630000]          	mov 	ah, [ptty] ; active (current) video page
   808 00000606 E854510000              	call	getc_n
   809 0000060B 59                      	pop	ecx
   810 0000060C 7502                    	jnz	short md_info_msg_ok
   811 0000060E E2ED                    	loop	md_info_msg_wait
   812                                  md_info_msg_ok:
   813                                  	; 30/06/2015
   814 00000610 E8E5230000              	call	sys_init
   815                                  	;
   816                                  	;jmp 	cpu_reset ; 22/02/2015
   817                                  hang:
   818                                  	; 27/02/2022
   819 00000615 29C0                    	sub	eax, eax
   820                                  _hang: 
   821                                  	; 23/02/2015
   822                                  	;sti			; Enable interrupts
   823 00000617 F4                      	hlt
   824                                  	;
   825                                  	;nop
   826                                  	;; 03/12/2014
   827                                  	;; 28/08/2014
   828                                  	;mov	ah, 11h
   829                                  	;call	getc
   830                                  	;jz      _c8
   831                                  	;
   832                                  	; 23/02/2015
   833                                  	; 06/02/2015
   834                                  	; 07/09/2014
   835 00000618 31DB                    	xor	ebx, ebx
   836 0000061A 8A1D[36630000]          	mov	bl, [ptty]	; active_page
   837 00000620 89DE                    	mov	esi, ebx
   838 00000622 66D1E6                  	shl 	si, 1
   839 00000625 81C6[38630000]          	add	esi, ttychr
   840 0000062B 668B06                  	mov	ax, [esi]
   841                                  	;and	ax, ax
   842                                  	;;jz	short _c8
   843                                  	;jz	short hang
   844                                  	; 27/02/2022
   845 0000062E 21C0                    	and	eax, eax
   846 00000630 74E5                    	jz	short _hang
   847 00000632 66C7060000              	mov	word [esi], 0
   848 00000637 80FB03                  	cmp	bl, 3		; Video page 3
   849                                  	;jb	short _c8
   850 0000063A 72D9                    	jb	short hang
   851                                  	;	
   852                                  	; 02/09/2014
   853 0000063C B40E                    	mov	ah, 0Eh		; Yellow character 
   854                                  				; on black background
   855                                  	; 27/02/2022 (32 bit reg push-pop)
   856                                  	; 07/09/2014
   857                                  nxtl:
   858                                  	;push	bx
   859 0000063E 53                      	push	ebx
   860                                  	;
   861                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   862                                  				; bh = 0 (video mode)
   863                                  				; Retro UNIX 386 v1 - Video Mode 0
   864                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   865 0000063F 50                      	push	eax
   866 00000640 E8770D0000              	call 	write_tty
   867 00000645 58                      	pop	eax
   868                                  	;pop	bx
   869 00000646 5B                      	pop	ebx
   870 00000647 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   871                                  	;jne	short _c8
   872 00000649 75CA                    	jne	short hang
   873 0000064B B00A                    	mov	al, 0Ah		; next line
   874 0000064D EBEF                    	jmp	short nxtl
   875                                  	
   876                                  ;_c8:
   877                                  ;	; 25/08/2014
   878                                  ;	cli				; Disable interrupts
   879                                  ;	mov	al, [scounter + 1]
   880                                  ;	and	al, al
   881                                  ;	jnz	hang
   882                                  ;	call	rtc_p
   883                                  ;	jmp     hang
   884                                  
   885                                  
   886                                  	; 27/08/2014
   887                                  	; 20/08/2014
   888                                  printk:
   889                                          ;mov    edi, [scr_row]
   890                                  pkl:
   891 0000064F AC                      	lodsb
   892 00000650 08C0                    	or 	al, al
   893 00000652 7404                    	jz	short pkr
   894 00000654 66AB                    	stosw
   895 00000656 EBF7                    	jmp	short pkl
   896                                  pkr:
   897 00000658 C3                      	retn
   898                                  
   899                                  ; 25/07/2015
   900                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   901                                  ; 17/02/2015
   902                                  ; 06/02/2015 (unix386.s)
   903                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   904                                  ;
   905                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   906                                  ;
   907                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   908                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   909                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   910                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   911                                  ;									       :
   912                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   913                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   914                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   915                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   916                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   917                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   918                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   919                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   920                                  ;-------------------------------------------------------------------------------
   921                                  ;
   922                                  
   923                                  timer_int:	; IRQ 0
   924                                  ;int_08h:	; Timer
   925                                  	; 14/10/2015
   926                                  	; Here, we are simulating system call entry (for task switch)
   927                                  	; (If multitasking is enabled, 
   928                                  	; 'clock' procedure may jump to 'sysrelease')
   929 00000659 1E                      	push	ds
   930 0000065A 06                      	push	es
   931 0000065B 0FA0                    	push	fs
   932 0000065D 0FA8                    	push	gs
   933 0000065F 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   934 00000660 66B91000                	mov     cx, KDATA
   935 00000664 8ED9                            mov     ds, cx
   936 00000666 8EC1                            mov     es, cx
   937 00000668 8EE1                            mov     fs, cx
   938 0000066A 8EE9                            mov     gs, cx
   939                                  	;
   940 0000066C 0F20D9                  	mov	ecx, cr3
   941 0000066F 890D[12070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   942                                  	;
   943 00000675 3B0D[08630000]          	cmp 	ecx, [k_page_dir]
   944 0000067B 741F                    	je	short T3
   945                                  	;
   946                                  	; timer interrupt has been occurred while OS is in user mode
   947 0000067D A3[C8660000]            	mov 	[u.r0], eax
   948 00000682 89E1                    	mov	ecx, esp
   949 00000684 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   950 00000687 890D[C0660000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   951 0000068D 8925[C4660000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   952                                  	;
   953 00000693 8B0D[08630000]          	mov	ecx, [k_page_dir]
   954 00000699 0F22D9                  	mov	cr3, ecx
   955                                  T3:
   956 0000069C FB                      	sti				; INTERRUPTS BACK ON
   957 0000069D 66FF05[84630000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   958 000006A4 7507                    	JNZ	short T4		; GO TO TEST_DAY
   959 000006A6 66FF05[86630000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   960                                  T4:					; TEST_DAY
   961 000006AD 66833D[86630000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   962 000006B5 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   963 000006B7 66813D[84630000]B0-     	CMP	word [TIMER_LOW],0B0H
   963 000006BF 00                 
   964 000006C0 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   965                                  
   966                                  ;-----	TIMER HAS GONE 24 HOURS
   967                                  	;;SUB	AX,AX
   968                                  	;MOV	[TIMER_HIGH],AX
   969                                  	;MOV	[TIMER_LOW],AX
   970 000006C2 29C0                    	sub	eax, eax
   971 000006C4 A3[84630000]            	mov	[TIMER_LH], eax
   972                                  	;	
   973 000006C9 C605[88630000]01        	MOV	byte [TIMER_OFL],1
   974                                  
   975                                  ;-----	TEST FOR DISKETTE TIME OUT
   976                                  
   977                                  T5:
   978                                  	; 23/12/2014
   979 000006D0 EB1D                    	jmp	short T6		; will be replaced with nop, nop
   980                                  					; (9090h) if a floppy disk
   981                                  					; is detected.
   982                                  	;mov	al,[CS:MOTOR_COUNT]
   983 000006D2 A0[8B630000]            	mov	al, [MOTOR_COUNT]
   984 000006D7 FEC8                    	dec	al
   985                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   986 000006D9 A2[8B630000]            	mov	[MOTOR_COUNT], al
   987                                  	;mov	[ORG_MOTOR_COUNT], al
   988 000006DE 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   989 000006E0 B0F0                    	mov 	al,0F0h
   990                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   991 000006E2 2005[8A630000]          	and	[MOTOR_STATUS], al
   992                                  	;and	[ORG_MOTOR_STATUS], al
   993 000006E8 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   994                                  					; bit 2 = enable controller
   995                                  					;	1 = normal operation
   996                                  					;	0 = reset	
   997                                  					; bit 0, 1 = drive select
   998                                  					; bit 4-7 = motor running bits 
   999 000006EA 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1000 000006EE EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1001                                  T6:	
  1002                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1003                                  					; TIMER TICK INTERRUPT
  1004                                  	;;inc	word [wait_count] ;;27/02/2015
  1005                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1006                                  	;;;;cli
  1007                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1008 000006EF FF15[0A070000]          	call	[x_timer] ; 14/05/2015
  1009                                  T7:
  1010                                  	; 14/10/2015
  1011 000006F5 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1012 000006F7 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1013 000006F8 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1014                                  	;
  1015 000006FA A1[12070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1016 000006FF 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1017                                  	;
  1018 00000702 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1019                                  	;
  1020 00000703 0FA9                    	pop	gs
  1021 00000705 0FA1                    	pop	fs
  1022 00000707 07                      	pop	es
  1023 00000708 1F                      	pop	ds
  1024 00000709 CF                      	iretd	; return from interrupt
  1025                                  
  1026                                  
  1027                                  ; ////////////////
  1028                                  
  1029                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1030                                  x_timer:
  1031 0000070A [16070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1032                                  	;dd	clock
  1033                                  
  1034                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1035                                  x_rtci:
  1036 0000070E [4B0A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1037                                  
  1038                                  ; 14/10/2015
  1039 00000712 00000000                cr3reg: dd 0
  1040                                  
  1041                                  	; 06/02/2015
  1042                                  	; 07/09/2014
  1043                                  	; 21/08/2014
  1044                                  u_timer:
  1045                                  	; 27/02/2022
  1046                                  	; 12/02/2022
  1047                                  ;timer_int:	; IRQ 0
  1048                                  	; 06/02/2015
  1049                                  	;push	eax
  1050                                  	;push	edx
  1051                                  	;push	ecx
  1052                                  	;push	ebx
  1053                                  	;push	ds
  1054                                  	;push	es
  1055                                  	;mov	eax, KDATA
  1056                                  	;mov	ds, ax
  1057                                  	;mov	es, ax
  1058 00000716 FF05[4C630000]          	inc	dword [tcount]
  1059 0000071C BB[D45E0000]            	mov	ebx, tcountstr + 4
  1060                                  	;mov	ax, [tcount]
  1061                                  	; 27/02/2022
  1062 00000721 A1[4C630000]            	mov	eax, [tcount]
  1063                                  	;mov	ecx, 10
  1064 00000726 31C9                    	xor	ecx, ecx
  1065 00000728 B10A                    	mov	cl, 10
  1066                                  rp_divtcnt:
  1067 0000072A 31D2                    	xor	edx, edx
  1068 0000072C F7F1                    	div	ecx
  1069 0000072E 80C230                  	add	dl, 30h
  1070 00000731 8813                    	mov	[ebx], dl
  1071                                  	;or	ax, ax
  1072                                  	; 27/02/2022
  1073 00000733 09C0                    	or	eax, eax
  1074 00000735 7403                    	jz	short print_lzero
  1075 00000737 4B                      	dec	ebx
  1076 00000738 EBF0                    	jmp	short rp_divtcnt
  1077                                  print_lzero:
  1078 0000073A 81FB[D05E0000]          	cmp	ebx, tcountstr
  1079 00000740 7606                    	jna	short print_tcount
  1080 00000742 4B                      	dec	ebx
  1081 00000743 C60330                   	mov	byte [ebx], 30h
  1082 00000746 EBF2                    	jmp	short print_lzero
  1083                                  print_tcount:
  1084 00000748 56                      	push	esi
  1085 00000749 57                      	push	edi
  1086 0000074A BE[AC5E0000]            	mov	esi, timer_msg ; Timer interrupt message
  1087                                  	;; 07/09/2014
  1088                                  	;mov	bx, 1		; Video page 1
  1089                                  	; 12/02/2022
  1090                                  	;mov	bx, 6		; Video page 6
  1091                                  	; 27/02/2022
  1092 0000074F 29DB                    	sub	ebx, ebx
  1093 00000751 B306                    	mov	bl, 6	; Video page 6
  1094                                  ptmsg:
  1095 00000753 AC                      	lodsb
  1096 00000754 08C0                    	or	al, al
  1097 00000756 740D                    	jz	short ptmsg_ok
  1098 00000758 56                      	push	esi
  1099                                  	;push	bx
  1100                                  	; 27/02/2022
  1101 00000759 53                              push	ebx
  1102 0000075A B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1103 0000075C E85B0C0000              	call 	write_tty
  1104                                  	;pop	bx
  1105                                  	; 27/02/2022
  1106 00000761 5B                      	pop	ebx
  1107 00000762 5E                      	pop	esi
  1108 00000763 EBEE                    	jmp	short ptmsg
  1109                                  	;; 27/08/2014
  1110                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1111                                  	;call	printk
  1112                                  	;
  1113                                  ptmsg_ok:
  1114                                  	; 07/09/2014
  1115                                  	;xor	dx, dx		; column 0, row 0
  1116                                  	; 27/02/2022
  1117 00000765 31D2                    	xor	edx, edx
  1118 00000767 E85A0D0000              	call	set_cpos	; set cursor position to 0,0 
  1119                                  	; 23/02/2015
  1120                                  	; 25/08/2014
  1121                                  	;mov	ebx, scounter		; (seconds counter)
  1122                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1123                                  ;	dec	byte [scounter+1]
  1124                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1125                                  ;	jns	short u_timer_retn
  1126                                  	; 26/02/2015
  1127                                  ;	call	rtc_p
  1128                                  ;	mov	ebx, scounter		; (seconds counter)
  1129                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1130                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1131                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1132                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1133                                  ;	mov	byte [ebx], 5
  1134                                  ;	inc	byte [ebx+1] ; 19
  1135                                  ;;timer_eoi:
  1136                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1137                                  ;;	out	20h, al	; 8259 PORT
  1138                                  	;
  1139                                  ;u_timer_retn:  ; 06/02/2015
  1140 0000076C 5F                      	pop	edi
  1141 0000076D 5E                      	pop	esi
  1142                                  	;pop	es
  1143                                  	;pop	ds
  1144                                  	;pop	ebx
  1145                                  	;pop	ecx
  1146                                  	;pop	edx
  1147                                  	;pop	eax
  1148                                  	;iret
  1149 0000076E C3                      	retn	; 06/02/2015
  1150                                  
  1151                                  	; 28/08/2014
  1152                                  irq0:
  1153 0000076F 6A00                            push 	dword 0
  1154 00000771 EB48                    	jmp	short which_irq
  1155                                  irq1:
  1156 00000773 6A01                            push 	dword 1
  1157 00000775 EB44                    	jmp	short which_irq
  1158                                  irq2:
  1159 00000777 6A02                            push 	dword 2
  1160 00000779 EB40                    	jmp	short which_irq
  1161                                  irq3:
  1162                                  	; 20/11/2015
  1163                                  	; 24/10/2015
  1164 0000077B 2EFF15[0B310000]        	call	dword [cs:com2_irq3]
  1165 00000782 6A03                    	push 	dword 3
  1166 00000784 EB35                    	jmp	short which_irq
  1167                                  irq4:
  1168                                  	; 20/11/2015
  1169                                  	; 24/10/2015
  1170 00000786 2EFF15[07310000]        	call	dword [cs:com1_irq4]
  1171 0000078D 6A04                            push 	dword 4
  1172 0000078F EB2A                    	jmp	short which_irq
  1173                                  irq5:
  1174 00000791 6A05                            push 	dword 5
  1175 00000793 EB26                    	jmp	short which_irq
  1176                                  irq6:
  1177 00000795 6A06                            push 	dword 6
  1178 00000797 EB22                    	jmp	short which_irq
  1179                                  irq7:
  1180 00000799 6A07                            push 	dword 7
  1181 0000079B EB1E                    	jmp	short which_irq
  1182                                  irq8:
  1183 0000079D 6A08                            push 	dword 8
  1184 0000079F EB1A                    	jmp	short which_irq
  1185                                  irq9:
  1186 000007A1 6A09                            push 	dword 9
  1187 000007A3 EB16                    	jmp	short which_irq
  1188                                  irq10:
  1189 000007A5 6A0A                            push 	dword 10
  1190 000007A7 EB12                    	jmp	short which_irq
  1191                                  irq11:
  1192 000007A9 6A0B                            push 	dword 11
  1193 000007AB EB0E                    	jmp	short which_irq
  1194                                  irq12:
  1195 000007AD 6A0C                            push 	dword 12
  1196 000007AF EB0A                    	jmp	short which_irq
  1197                                  irq13:
  1198 000007B1 6A0D                            push 	dword 13
  1199 000007B3 EB06                    	jmp	short which_irq
  1200                                  irq14:
  1201 000007B5 6A0E                            push 	dword 14
  1202 000007B7 EB02                    	jmp	short which_irq
  1203                                  irq15:
  1204 000007B9 6A0F                            push 	dword 15
  1205                                  	;jmp	short which_irq
  1206                                  
  1207                                  	; 27/02/2022
  1208                                  	; 19/10/2015
  1209                                  	; 29/08/2014
  1210                                  	; 21/08/2014
  1211                                  which_irq:
  1212 000007BB 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1213 000007BE 53                      	push	ebx
  1214 000007BF 56                      	push	esi
  1215 000007C0 57                      	push	edi
  1216 000007C1 1E                      	push 	ds
  1217 000007C2 06                      	push 	es
  1218                                  	;
  1219 000007C3 88C3                    	mov	bl, al
  1220                                  	;
  1221 000007C5 B810000000              	mov	eax, KDATA
  1222 000007CA 8ED8                    	mov	ds, ax
  1223 000007CC 8EC0                    	mov	es, ax
  1224                                  	; 19/10/2015
  1225 000007CE FC                      	cld
  1226                                          ; 27/08/2014
  1227 000007CF 8105[5C5E0000]A000-             add     dword [scr_row], 0A0h
  1227 000007D7 0000               
  1228                                  	;
  1229 000007D9 B417                    	mov	ah, 17h	; blue (1) background, 
  1230                                  			; light gray (7) forecolor
  1231 000007DB 8B3D[5C5E0000]                  mov     edi, [scr_row]
  1232 000007E1 B049                    	mov	al, 'I'
  1233 000007E3 66AB                    	stosw
  1234 000007E5 B052                    	mov	al, 'R'
  1235 000007E7 66AB                    	stosw
  1236 000007E9 B051                    	mov	al, 'Q'
  1237 000007EB 66AB                    	stosw
  1238 000007ED B020                    	mov	al, ' '
  1239 000007EF 66AB                    	stosw
  1240 000007F1 88D8                    	mov	al, bl
  1241 000007F3 3C0A                    	cmp	al, 10
  1242 000007F5 7208                    	jb	short iix
  1243 000007F7 B031                    	mov	al, '1'
  1244 000007F9 66AB                    	stosw
  1245 000007FB 88D8                    	mov	al, bl
  1246 000007FD 2C0A                    	sub	al, 10
  1247                                  iix:
  1248 000007FF 0430                    	add	al, '0'
  1249 00000801 66AB                    	stosw
  1250 00000803 B020                    	mov	al, ' '
  1251 00000805 66AB                    	stosw
  1252 00000807 B021                    	mov	al, '!'
  1253 00000809 66AB                    	stosw
  1254 0000080B B020                    	mov	al, ' '
  1255 0000080D 66AB                    	stosw
  1256                                  	; 23/02/2015
  1257 0000080F 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1258                                  	;jna	iiret
  1259                                  	; 27/02/2022
  1260 00000812 7604                    	jna	short iiz
  1261                                  iiy:
  1262 00000814 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1263 00000816 E6A0                    	out	0A0h, al ; the 2nd 8259
  1264                                  iiz:
  1265 00000818 E983010000              	jmp     iiret
  1266                                  	;
  1267                                  	; 22/08/2014
  1268                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1269                                  	;out	20h, al	; 8259 PORT
  1270                                  	;
  1271                                  	;pop	es
  1272                                  	;pop	ds
  1273                                  	;pop	edi
  1274                                  	;pop	esi
  1275                                  	;pop	ebx
  1276                                  	;pop 	eax
  1277                                  	;iret
  1278                                  
  1279                                  	; 02/04/2015
  1280                                  	; 25/08/2014
  1281                                  exc0:
  1282 0000081D 6A00                            push 	dword 0
  1283 0000081F E990000000                      jmp     cpu_except
  1284                                  exc1:
  1285 00000824 6A01                            push 	dword 1
  1286 00000826 E989000000                      jmp     cpu_except
  1287                                  exc2:
  1288 0000082B 6A02                            push 	dword 2
  1289 0000082D E982000000                      jmp     cpu_except
  1290                                  exc3:
  1291 00000832 6A03                            push 	dword 3
  1292 00000834 EB7E                            jmp     cpu_except
  1293                                  exc4:
  1294 00000836 6A04                            push 	dword 4
  1295 00000838 EB7A                            jmp     cpu_except
  1296                                  exc5:
  1297 0000083A 6A05                            push 	dword 5
  1298 0000083C EB76                            jmp     cpu_except
  1299                                  exc6:
  1300 0000083E 6A06                            push 	dword 6
  1301 00000840 EB72                            jmp     cpu_except
  1302                                  exc7:
  1303 00000842 6A07                            push 	dword 7
  1304 00000844 EB6E                            jmp     cpu_except
  1305                                  exc8:
  1306                                  	; [esp] = Error code
  1307 00000846 6A08                            push 	dword 8
  1308 00000848 EB5C                            jmp     cpu_except_en
  1309                                  exc9:
  1310 0000084A 6A09                            push 	dword 9
  1311 0000084C EB66                            jmp     cpu_except
  1312                                  exc10:
  1313                                  	; [esp] = Error code
  1314 0000084E 6A0A                            push 	dword 10
  1315 00000850 EB54                            jmp     cpu_except_en
  1316                                  exc11:
  1317                                  	; [esp] = Error code
  1318 00000852 6A0B                            push 	dword 11
  1319 00000854 EB50                            jmp     cpu_except_en
  1320                                  exc12:
  1321                                  	; [esp] = Error code
  1322 00000856 6A0C                            push 	dword 12
  1323 00000858 EB4C                            jmp     cpu_except_en
  1324                                  exc13:
  1325                                  	; [esp] = Error code
  1326 0000085A 6A0D                            push 	dword 13
  1327 0000085C EB48                            jmp     cpu_except_en
  1328                                  exc14:
  1329                                  	; [esp] = Error code
  1330 0000085E 6A0E                            push 	dword 14
  1331 00000860 EB44                    	jmp	short cpu_except_en
  1332                                  exc15:
  1333 00000862 6A0F                            push 	dword 15
  1334 00000864 EB4E                            jmp     cpu_except
  1335                                  exc16:
  1336 00000866 6A10                            push 	dword 16
  1337 00000868 EB4A                            jmp     cpu_except
  1338                                  exc17:
  1339                                  	; [esp] = Error code
  1340 0000086A 6A11                            push 	dword 17
  1341 0000086C EB38                    	jmp	short cpu_except_en
  1342                                  exc18:
  1343 0000086E 6A12                            push 	dword 18
  1344 00000870 EB42                    	jmp	short cpu_except
  1345                                  exc19:
  1346 00000872 6A13                            push 	dword 19
  1347 00000874 EB3E                    	jmp	short cpu_except
  1348                                  exc20:
  1349 00000876 6A14                            push 	dword 20
  1350 00000878 EB3A                    	jmp	short cpu_except
  1351                                  exc21:
  1352 0000087A 6A15                            push 	dword 21
  1353 0000087C EB36                    	jmp	short cpu_except
  1354                                  exc22:
  1355 0000087E 6A16                            push 	dword 22
  1356 00000880 EB32                    	jmp	short cpu_except
  1357                                  exc23:
  1358 00000882 6A17                            push 	dword 23
  1359 00000884 EB2E                    	jmp	short cpu_except
  1360                                  exc24:
  1361 00000886 6A18                            push 	dword 24
  1362 00000888 EB2A                    	jmp	short cpu_except
  1363                                  exc25:
  1364 0000088A 6A19                            push 	dword 25
  1365 0000088C EB26                    	jmp	short cpu_except
  1366                                  exc26:
  1367 0000088E 6A1A                            push 	dword 26
  1368 00000890 EB22                    	jmp	short cpu_except
  1369                                  exc27:
  1370 00000892 6A1B                            push 	dword 27
  1371 00000894 EB1E                    	jmp	short cpu_except
  1372                                  exc28:
  1373 00000896 6A1C                            push 	dword 28
  1374 00000898 EB1A                    	jmp	short cpu_except
  1375                                  exc29:
  1376 0000089A 6A1D                            push 	dword 29
  1377 0000089C EB16                    	jmp	short cpu_except
  1378                                  exc30:
  1379 0000089E 6A1E                            push 	dword 30
  1380 000008A0 EB04                    	jmp	short cpu_except_en
  1381                                  exc31:
  1382 000008A2 6A1F                            push 	dword 31
  1383 000008A4 EB0E                            jmp     short cpu_except
  1384                                  
  1385                                  	; 27/02/2022
  1386                                  	; 19/10/2015
  1387                                  	; 19/09/2015
  1388                                  	; 01/09/2015
  1389                                  	; 28/08/2015
  1390                                  	; 28/08/2014
  1391                                  cpu_except_en:
  1392 000008A6 87442404                	xchg	eax, [esp+4] ; Error code
  1393 000008AA 36A3[B4630000]          	mov	[ss:error_code], eax
  1394 000008B0 58                      	pop	eax  ; Exception number
  1395 000008B1 870424                  	xchg	eax, [esp]
  1396                                  		; eax = eax before exception
  1397                                  		; [esp] -> exception number
  1398                                  		; [esp+4] -> EIP to return
  1399                                  	; 19/10/2015
  1400                                  	; 19/09/2015
  1401                                  	; 01/09/2015
  1402                                  	; 28/08/2015
  1403                                  	; 29/08/2014
  1404                                  	; 28/08/2014
  1405                                  	; 25/08/2014
  1406                                  	; 21/08/2014
  1407                                  cpu_except:	; CPU Exceptions
  1408 000008B4 FC                      	cld
  1409 000008B5 870424                  	xchg	eax, [esp] 
  1410                                  		; eax = Exception number
  1411                                  		; [esp] = eax (before exception)	
  1412 000008B8 53                      	push	ebx
  1413 000008B9 56                      	push	esi
  1414 000008BA 57                      	push	edi
  1415 000008BB 1E                      	push 	ds
  1416 000008BC 06                      	push 	es
  1417                                  	; 28/08/2015
  1418 000008BD 66BB1000                	mov	bx, KDATA
  1419 000008C1 8EDB                    	mov	ds, bx
  1420 000008C3 8EC3                    	mov	es, bx
  1421 000008C5 0F20DB                  	mov	ebx, cr3
  1422 000008C8 53                      	push	ebx ; (*) page directory
  1423                                  	; 19/10/2015
  1424 000008C9 FC                      	cld
  1425                                  	; 25/03/2015
  1426 000008CA 8B1D[08630000]          	mov	ebx, [k_page_dir]
  1427 000008D0 0F22DB                  	mov	cr3, ebx
  1428                                  	; 28/08/2015
  1429 000008D3 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1430 000008D6 7513                    	jne	short cpu_except_nfp
  1431 000008D8 E8D71E0000              	call	page_fault_handler
  1432 000008DD 21C0                    	and 	eax, eax
  1433                                          ;jz	iiretp ; 01/09/2015
  1434                                  	; 27/02/2022
  1435 000008DF 7505                    	jnz	short cpu_except_pf
  1436 000008E1 E9B6000000              	jmp	iiretp
  1437                                  cpu_except_pf:
  1438 000008E6 B80E000000              	mov	eax, 0Eh ; 14
  1439                                  cpu_except_nfp:
  1440                                  	; 02/04/2015
  1441 000008EB BB[15060000]            	mov	ebx, hang
  1442 000008F0 875C241C                	xchg	ebx, [esp+28]
  1443                                  		; EIP (points to instruction which faults)
  1444                                  	  	; New EIP (hang)
  1445 000008F4 891D[B8630000]          	mov	[FaultOffset], ebx
  1446 000008FA C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1447 00000902 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1448                                  	;
  1449 0000090A 88C4                    	mov	ah, al
  1450 0000090C 240F                    	and	al, 0Fh
  1451 0000090E 3C09                    	cmp	al, 9
  1452 00000910 7602                    	jna	short h1ok
  1453 00000912 0407                    	add	al, 'A'-':'
  1454                                  h1ok:
  1455 00000914 D0EC                    	shr	ah, 1
  1456 00000916 D0EC                    	shr	ah, 1
  1457 00000918 D0EC                    	shr	ah, 1
  1458 0000091A D0EC                    	shr	ah, 1
  1459 0000091C 80FC09                  	cmp	ah, 9
  1460 0000091F 7603                    	jna	short h2ok
  1461 00000921 80C407                  	add	ah, 'A'-':'
  1462                                  h2ok:	
  1463 00000924 86E0                    	xchg 	ah, al	
  1464 00000926 66053030                	add	ax, '00'
  1465 0000092A 66A3[E85E0000]          	mov	[excnstr], ax
  1466                                  	;
  1467                                  	; 29/08/2014
  1468 00000930 A1[B8630000]            	mov	eax, [FaultOffset]
  1469 00000935 51                      	push	ecx
  1470 00000936 52                      	push	edx
  1471 00000937 89E3                    	mov	ebx, esp
  1472                                  	; 28/08/2015
  1473 00000939 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1474                                  			  ; to hexadecimal string
  1475                                  	;mov	ecx, 10	    ; divisor to convert	
  1476                                  			    ; binary number to decimal string
  1477                                  b2d1:
  1478 0000093E 31D2                    	xor	edx, edx
  1479 00000940 F7F1                    	div	ecx
  1480                                  	;push	dx
  1481                                  	; 27/02/2022
  1482 00000942 52                      	push	edx
  1483 00000943 39C8                    	cmp	eax, ecx
  1484 00000945 73F7                    	jnb	short b2d1
  1485 00000947 BF[F35E0000]            	mov	edi, EIPstr ; EIP value
  1486                                  			    ; points to instruction which faults	
  1487                                  	; 28/08/2015
  1488 0000094C 89C2                    	mov	edx, eax
  1489                                  b2d2:
  1490                                  	;add	al, '0'
  1491 0000094E 8A82[FC160000]          	mov	al, [edx+hexchrs]
  1492 00000954 AA                      	stosb		    ; write hexadecimal digit to its place	
  1493 00000955 39E3                    	cmp	ebx, esp
  1494 00000957 7605                    	jna	short b2d3
  1495                                  	; 27/02/2022
  1496 00000959 58                      	pop	eax
  1497                                  	;pop	ax
  1498 0000095A 88C2                    	mov	dl, al
  1499 0000095C EBF0                    	jmp	short b2d2
  1500                                  b2d3:
  1501 0000095E B068                    	mov 	al, 'h' ; 28/08/2015
  1502 00000960 AA                      	stosb
  1503 00000961 B020                    	mov	al, 20h	    ; space
  1504 00000963 AA                      	stosb
  1505 00000964 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1506 00000966 AA                      	stosb
  1507                                  	;
  1508 00000967 5A                      	pop	edx
  1509 00000968 59                      	pop	ecx
  1510                                  	;
  1511 00000969 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1512                                  			; white (F) forecolor
  1513 0000096B BE[D85E0000]            	mov	esi, exc_msg ; message offset
  1514                                  	;
  1515 00000970 EB11                    	jmp	short piemsg
  1516                                  	;
  1517                                          ;add    dword [scr_row], 0A0h
  1518                                          ;mov    edi, [scr_row]
  1519                                          ;
  1520                                  	;call 	printk
  1521                                  	;
  1522                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1523                                  	;out	20h, al	; 8259 PORT
  1524                                  	;
  1525                                  	;pop	es
  1526                                  	;pop	ds
  1527                                  	;pop	edi
  1528                                  	;pop	esi
  1529                                  	;pop 	eax
  1530                                  	;iret
  1531                                  	
  1532                                  	; 28/08/2015
  1533                                  	; 23/02/2015
  1534                                  	; 20/08/2014
  1535                                  ignore_int:
  1536 00000972 50                      	push	eax
  1537 00000973 53                      	push	ebx ; 23/02/2015
  1538 00000974 56                      	push	esi
  1539 00000975 57                      	push	edi
  1540 00000976 1E                      	push 	ds
  1541 00000977 06                      	push 	es
  1542                                  	; 28/08/2015
  1543 00000978 0F20D8                  	mov	eax, cr3
  1544 0000097B 50                      	push	eax ; (*) page directory
  1545                                  	;
  1546 0000097C B467                    	mov	ah, 67h	; brown (6) background, 
  1547                                  			; light gray (7) forecolor
  1548 0000097E BE[965E0000]            	mov	esi, int_msg ; message offset
  1549                                  piemsg:
  1550                                          ; 27/08/2014
  1551 00000983 8105[5C5E0000]A000-             add     dword [scr_row], 0A0h
  1551 0000098B 0000               
  1552 0000098D 8B3D[5C5E0000]                  mov     edi, [scr_row]
  1553                                          ;
  1554 00000993 E8B7FCFFFF              	call 	printk
  1555                                  	;
  1556                                  	; 23/02/2015
  1557 00000998 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1558 0000099A E6A0                    	out	0A0h, al ; the 2nd 8259
  1559                                  iiretp: ; 01/09/2015
  1560                                  	; 28/08/2015
  1561 0000099C 58                      	pop	eax ; (*) page directory
  1562 0000099D 0F22D8                  	mov	cr3, eax
  1563                                  	;
  1564                                  iiret:
  1565                                  	; 22/08/2014
  1566 000009A0 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1567 000009A2 E620                    	out	20h, al	; 8259 PORT
  1568                                  	;
  1569 000009A4 07                      	pop	es
  1570 000009A5 1F                      	pop	ds
  1571 000009A6 5F                      	pop	edi
  1572 000009A7 5E                      	pop	esi
  1573 000009A8 5B                      	pop	ebx ; 29/08/2014
  1574 000009A9 58                      	pop 	eax
  1575 000009AA CF                      	iretd
  1576                                  
  1577                                  	; 23/02/2022
  1578                                  	; 26/02/2015
  1579                                  	; 07/09/2014
  1580                                  	; 25/08/2014
  1581                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1582                                  	; 22/08/2014
  1583 000009AB 50                      	push	eax
  1584 000009AC 53                      	push	ebx ; 29/08/2014
  1585 000009AD 56                      	push	esi
  1586 000009AE 57                      	push	edi
  1587 000009AF 1E                      	push 	ds
  1588 000009B0 06                      	push 	es
  1589                                  	;
  1590 000009B1 B810000000              	mov	eax, KDATA
  1591 000009B6 8ED8                    	mov	ds, ax
  1592 000009B8 8EC0                    	mov	es, ax
  1593                                  	;
  1594                                  	; 25/08/2014
  1595                                  	;call	rtc_p
  1596                                  	; 23/02/2022
  1597 000009BA FF15[0E070000]          	call	[x_rtci]
  1598                                  	;
  1599                                  	; 22/02/2015 - dsectpm.s
  1600                                  	; [ source: http://wiki.osdev.org/RTC ]
  1601                                  	; read status register C to complete procedure
  1602                                  	;(it is needed to get a next IRQ 8) 
  1603 000009C0 B00C                    	mov	al, 0Ch ; 
  1604 000009C2 E670                    	out	70h, al ; select register C
  1605 000009C4 90                      	nop
  1606 000009C5 E471                    	in	al, 71h ; just throw away contents
  1607                                  	; 22/02/2015
  1608 000009C7 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1609 000009C9 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1610                                  	;
  1611 000009CB EBD3                    	jmp	short iiret	
  1612                                  
  1613                                  	; 22/08/2014
  1614                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1615                                  	; (INT 1Ah)
  1616                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1617                                  time_of_day:
  1618 000009CD E868010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1619 000009D2 726F                            jc      short rtc_retn 
  1620 000009D4 B000                    	mov	al, CMOS_SECONDS
  1621 000009D6 E847010000              	call	CMOS_READ
  1622 000009DB A2[7C630000]            	mov	[time_seconds], al 
  1623 000009E0 B002                    	mov	al, CMOS_MINUTES
  1624 000009E2 E83B010000              	call	CMOS_READ
  1625 000009E7 A2[7D630000]            	mov	[time_minutes], al 
  1626 000009EC B004                    	mov	al, CMOS_HOURS
  1627 000009EE E82F010000              	call	CMOS_READ
  1628 000009F3 A2[7E630000]                    mov     [time_hours], al
  1629 000009F8 B006                    	mov	al, CMOS_DAY_WEEK 
  1630 000009FA E823010000              	call	CMOS_READ
  1631 000009FF A2[7F630000]            	mov	[date_wday], al
  1632 00000A04 B007                     	mov	al, CMOS_DAY_MONTH
  1633 00000A06 E817010000              	call	CMOS_READ
  1634 00000A0B A2[80630000]            	mov	[date_day], al
  1635 00000A10 B008                    	mov	al, CMOS_MONTH
  1636 00000A12 E80B010000              	call	CMOS_READ
  1637 00000A17 A2[81630000]            	mov	[date_month], al
  1638 00000A1C B009                    	mov	al, CMOS_YEAR
  1639 00000A1E E8FF000000              	call	CMOS_READ
  1640 00000A23 A2[82630000]            	mov	[date_year], al
  1641 00000A28 B032                    	mov	al, CMOS_CENTURY
  1642 00000A2A E8F3000000              	call	CMOS_READ
  1643 00000A2F A2[83630000]            	mov	[date_century], al
  1644                                  	;
  1645 00000A34 B000                    	mov	al, CMOS_SECONDS
  1646 00000A36 E8E7000000              	call 	CMOS_READ
  1647 00000A3B 3A05[7C630000]          	cmp	al, [time_seconds]
  1648 00000A41 758A                    	jne	short time_of_day
  1649                                  
  1650                                  rtc_retn:
  1651 00000A43 C3                      	retn
  1652                                  
  1653                                  rtci_default:
  1654                                  	; 23/02/2022 (Temporary!)
  1655                                  	; (default real time clock handler in multitasking mode)
  1656                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1657 00000A44 FF05[C0630000]          	inc	dword [rtc_ticks] ; real time clock counter
  1658                                  			; (not used in anywhere of kernel for now!)
  1659 00000A4A C3                      	retn
  1660                                  
  1661                                  rtc_p:	
  1662                                  	; 27/02/2022
  1663                                  	; 12/02/2022
  1664                                  	; 07/09/2014
  1665                                  	; 29/08/2014
  1666                                  	; 27/08/2014
  1667                                  	; 25/08/2014
  1668                                   	; Print Real Time Clock content
  1669                                  	;
  1670                                  	;
  1671 00000A4B E87DFFFFFF              	call	time_of_day
  1672 00000A50 72F1                    	jc	short rtc_retn
  1673                                  	;
  1674 00000A52 3A05[4A5F0000]          	cmp	al, [ptime_seconds]
  1675 00000A58 74E9                            je      short rtc_retn ; 29/08/2014
  1676                                  	;
  1677 00000A5A A2[4A5F0000]            	mov	[ptime_seconds], al
  1678                                  	;
  1679 00000A5F A0[83630000]            	mov	al, [date_century]
  1680 00000A64 E8EC000000              	call	bcd_to_ascii
  1681 00000A69 66A3[175F0000]          	mov	[datestr+6], ax
  1682 00000A6F A0[82630000]            	mov	al, [date_year]
  1683 00000A74 E8DC000000              	call	bcd_to_ascii
  1684 00000A79 66A3[195F0000]          	mov	[datestr+8], ax
  1685 00000A7F A0[81630000]            	mov	al, [date_month]
  1686 00000A84 E8CC000000              	call	bcd_to_ascii
  1687 00000A89 66A3[145F0000]          	mov	[datestr+3], ax
  1688 00000A8F A0[80630000]            	mov	al, [date_day]
  1689 00000A94 E8BC000000              	call	bcd_to_ascii
  1690 00000A99 66A3[115F0000]          	mov	[datestr], ax
  1691                                  	;
  1692 00000A9F 0FB61D[7F630000]        	movzx	ebx, byte [date_wday]
  1693 00000AA6 C0E302                  	shl 	bl, 2
  1694 00000AA9 81C3[2A5F0000]          	add	ebx, daytmp
  1695 00000AAF 8B03                    	mov	eax, [ebx]
  1696 00000AB1 A3[1C5F0000]            	mov	[daystr], eax
  1697                                  	;
  1698 00000AB6 A0[7E630000]            	mov	al, [time_hours]
  1699 00000ABB E895000000              	call	bcd_to_ascii
  1700 00000AC0 66A3[205F0000]          	mov	[timestr], ax
  1701 00000AC6 A0[7D630000]            	mov	al, [time_minutes]
  1702 00000ACB E885000000              	call	bcd_to_ascii
  1703 00000AD0 66A3[235F0000]          	mov	[timestr+3], ax
  1704 00000AD6 A0[7C630000]            	mov	al, [time_seconds]
  1705 00000ADB E875000000              	call	bcd_to_ascii
  1706 00000AE0 66A3[265F0000]          	mov	[timestr+6], ax
  1707                                  	;		
  1708 00000AE6 BE[FF5E0000]            	mov	esi, rtc_msg ; message offset
  1709                                  	; 23/02/2015
  1710 00000AEB 52                      	push	edx
  1711 00000AEC 51                      	push	ecx
  1712                                  	; 07/09/2014
  1713                                  	;mov	bx, 2	; Video page 2
  1714                                  	; 27/02/2022
  1715 00000AED 29DB                    	sub	ebx, ebx
  1716 00000AEF B307                    	mov	bl, 7	; Video page 7
  1717                                  prtmsg:
  1718 00000AF1 AC                      	lodsb
  1719 00000AF2 08C0                    	or	al, al
  1720 00000AF4 740D                    	jz	short prtmsg_ok
  1721 00000AF6 56                      	push	esi
  1722                                  	; 27/02/2022
  1723 00000AF7 53                      	push	ebx
  1724                                  	;push	bx
  1725 00000AF8 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1726                                  			; white (F) forecolor
  1727 00000AFA E8BD080000              	call 	write_tty
  1728                                  	;pop	bx
  1729                                  	; 27/02/2022
  1730 00000AFF 5B                      	pop	ebx
  1731 00000B00 5E                      	pop	esi
  1732 00000B01 EBEE                    	jmp	short prtmsg
  1733                                  	;
  1734                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1735                                  	;call	printk
  1736                                  prtmsg_ok:
  1737                                  	; 07/09/2014
  1738                                  	;xor	dx, dx		; column 0, row 0
  1739                                  	; 27/02/2022
  1740 00000B03 31D2                    	xor	edx, edx
  1741 00000B05 E8BC090000              	call	set_cpos	; set cursor position to 0,0 
  1742                                  	; 23/02/2015
  1743 00000B0A 59                      	pop	ecx
  1744 00000B0B 5A                      	pop	edx
  1745 00000B0C C3                      	retn
  1746                                  
  1747                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1748                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1749                                  default_irq7:
  1750                                  	; 27/02/2022
  1751                                  	;push	ax
  1752 00000B0D 50                      	push	eax
  1753 00000B0E B00B                    	mov	al, 0Bh  ; In-Service register
  1754 00000B10 E620                    	out	20h, al
  1755 00000B12 EB00                            jmp short $+2
  1756 00000B14 EB00                    	jmp short $+2
  1757 00000B16 E420                    	in	al, 20h
  1758 00000B18 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1759 00000B1A 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1760 00000B1C B020                            mov     al, 20h ; EOI
  1761 00000B1E E620                    	out	20h, al 
  1762                                  irq7_iret:
  1763                                  	;pop	ax
  1764                                  	; 27/02/2022
  1765 00000B20 58                      	pop	eax
  1766 00000B21 CF                      	iretd
  1767                                  	
  1768                                  	; 22/08/2014
  1769                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1770                                  CMOS_READ:
  1771 00000B22 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1772 00000B23 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1773 00000B25 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1774 00000B26 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1775 00000B28 FA                      	cli		; DISABLE INTERRUPTS
  1776 00000B29 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1777 00000B2B 90                      	nop		; I/O DELAY
  1778 00000B2C E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1779 00000B2E 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1780                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1781                                  		     ; ----- 10/06/85 (test4.asm)
  1782 00000B30 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1783                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1784 00000B32 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1785 00000B34 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1786 00000B36 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1787 00000B38 9D                      	popf	
  1788 00000B39 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1789                                  
  1790                                  	; 22/08/2014
  1791                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1792                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1793 00000B3A 51                      	push	ecx
  1794 00000B3B B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1795                                  		; mov cx, 800	
  1796                                  UPD_10:
  1797 00000B40 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1798 00000B42 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1799 00000B43 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1800 00000B48 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1801 00000B4A 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1802 00000B4C FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1803 00000B4D E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1804 00000B4F 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1805                                  		; xor ax, ax
  1806 00000B51 F9                      	stc				; SET CARRY FOR ERROR
  1807                                  UPD_90:
  1808 00000B52 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1809 00000B53 FA                      	cli				; INTERRUPTS OFF DURING SET
  1810 00000B54 C3                      	retn				; RETURN WITH CY FLAG SET
  1811                                  
  1812                                  bcd_to_ascii:
  1813                                  	; 25/08/2014
  1814                                  	; INPUT ->
  1815                                  	;	al = Packed BCD number
  1816                                  	; OUTPUT ->
  1817                                  	;	ax  = ASCII word/number
  1818                                  	;
  1819                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1820                                  	;
  1821 00000B55 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1822                                  					; AH = AL / 10h
  1823                                  					; AL = AL MOD 10h
  1824 00000B57 660D3030                	or ax,'00'                      ; Make it ASCII based
  1825                                  
  1826 00000B5B 86E0                            xchg ah, al 
  1827                                  	
  1828 00000B5D C3                      	retn	
  1829                                  	
  1830                                  %include 'keyboard.inc' ; 07/03/2015
  1831                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KEYBOARD.INC
  1832                              <1> ; Last Modification: 13/06/2022
  1833                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1834                              <1> ;
  1835                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1836                              <1> 
  1837                              <1> ; 13/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  1838                              <1> ; 23/02/2022 
  1839                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1840                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1841                              <1> ; 30/06/2015
  1842                              <1> ; 11/03/2015
  1843                              <1> ; 28/02/2015
  1844                              <1> ; 25/02/2015
  1845                              <1> ; 20/02/2015
  1846                              <1> ; 18/02/2015
  1847                              <1> ; 03/12/2014
  1848                              <1> ; 07/09/2014
  1849                              <1> ; KEYBOARD INTERRUPT HANDLER
  1850                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1851                              <1> 
  1852                              <1> ;getch:
  1853                              <1> ;	; 18/02/2015
  1854                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1855                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1856                              <1> ;	; routine, later... (multi tasking ability)
  1857                              <1> ;	; 28/02/2015
  1858                              <1> ;	sti	; enable interrupts
  1859                              <1> ;	;
  1860                              <1> ;	;push	esi
  1861                              <1> ;	;push	ebx
  1862                              <1> ;	;xor	ebx, ebx
  1863                              <1> ;	;mov	bl, [ptty]  ; active_page
  1864                              <1> ;	;mov	esi, ebx
  1865                              <1> ;	;shl 	si, 1
  1866                              <1> ;	;add	esi, ttychr
  1867                              <1> ;getch_1:
  1868                              <1> ;	;mov	ax, [esi]
  1869                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1870                              <1> ;	and	ax, ax
  1871                              <1> ;	jz	short getch_2
  1872                              <1> ;	mov	word [ttychr], 0
  1873                              <1> ;	;mov	word [esi], 0
  1874                              <1> ;	;pop	ebx
  1875                              <1> ;	;pop	esi
  1876                              <1> ;	retn
  1877                              <1> ;getch_2:
  1878                              <1> ;	hlt	; not proper for multi tasking!
  1879                              <1> ;		; (temporary halt for now)
  1880                              <1> ;		; 'sleep' on tty 
  1881                              <1> ;		; will (must) be located here		
  1882                              <1> ;	nop
  1883                              <1> ;	jmp	short getch_1
  1884                              <1> 
  1885                              <1> keyb_int:
  1886                              <1> 	; 23/02/2022
  1887                              <1> 	; 30/06/2015
  1888                              <1> 	; 25/02/2015
  1889                              <1> 	; 20/02/2015
  1890                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1891                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1892                              <1> 	; 30/06/2014
  1893                              <1> 	; 10/05/2013	
  1894                              <1>       	; Retro Unix 8086 v1 feature only!
  1895                              <1> 	; 03/03/2014
  1896                              <1> 	
  1897 00000B5E 1E                  <1> 	push	ds
  1898 00000B5F 53                  <1> 	push	ebx
  1899 00000B60 50                  <1> 	push	eax
  1900                              <1> 	;
  1901                              <1> 	; 23/02/2022
  1902 00000B61 9C                  <1> 	pushfd
  1903 00000B62 0E                  <1> 	push	cs
  1904                              <1> 	;mov	ax, KDATA
  1905 00000B63 31C0                <1> 	xor	eax, eax
  1906 00000B65 B010                <1> 	mov	al, KDATA
  1907 00000B67 8ED8                <1> 	mov	ds, ax
  1908                              <1> 	;
  1909                              <1> 	;pushfd
  1910                              <1> 	;push	cs
  1911 00000B69 E810020000          <1> 	call	kb_int   ; int_09h
  1912                              <1> 	;
  1913 00000B6E B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1914                              <1> 	;call	getc
  1915 00000B70 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1916 00000B75 744E                <1> 	jz	short keyb_int4
  1917                              <1> 	;
  1918 00000B77 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1919                              <1> 	;call	getc
  1920 00000B79 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1921                              <1> 	;
  1922                              <1> 	; 20/02/2015
  1923 00000B7E 0FB61D[36630000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1924                              <1> 	;
  1925 00000B85 20C0                <1> 	and 	al, al
  1926 00000B87 751D                <1> 	jnz	short keyb_int1
  1927                              <1> 	;
  1928 00000B89 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1929 00000B8C 7218                <1> 	jb	short keyb_int1
  1930 00000B8E 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1931 00000B91 7713                <1> 	ja	short keyb_int1
  1932                              <1> 	;
  1933 00000B93 88D8                <1> 	mov	al, bl
  1934 00000B95 0468                <1> 	add	al, 68h
  1935 00000B97 38E0                <1> 	cmp	al, ah
  1936 00000B99 7409                <1> 	je	short keyb_int0
  1937 00000B9B 88E0                <1> 	mov	al, ah
  1938 00000B9D 2C68                <1> 	sub	al, 68h
  1939 00000B9F E8370A0000          <1> 	call	tty_sw
  1940                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1941                              <1> keyb_int0: ; 30/06/2015
  1942                              <1> 	;xor	ax, ax
  1943                              <1> 	; 23/02/2022
  1944 00000BA4 31C0                <1> 	xor	eax, eax
  1945                              <1> keyb_int1:
  1946 00000BA6 D0E3                <1> 	shl	bl, 1
  1947 00000BA8 81C3[38630000]      <1> 	add	ebx, ttychr
  1948                              <1> 	;
  1949                              <1> 	;23/02/2022
  1950 00000BAE 09C0                <1> 	or	eax, eax
  1951                              <1> 	;or	ax, ax
  1952 00000BB0 7406                <1> 	jz	short keyb_int2
  1953                              <1> 	;
  1954 00000BB2 66833B00            <1> 	cmp 	word [ebx], 0
  1955 00000BB6 7703                <1>         ja      short keyb_int3 
  1956                              <1> keyb_int2:
  1957 00000BB8 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1958                              <1> 			   ; and scan code of the character
  1959                              <1> 			   ; for current tty (or last tty
  1960                              <1> 			   ; just before tty switch).
  1961                              <1> keyb_int3:
  1962 00000BBB A0[36630000]        <1>         mov     al, [ptty]
  1963 00000BC0 E84A3B0000          <1> 	call	wakeup
  1964                              <1> 	;
  1965                              <1> keyb_int4:
  1966 00000BC5 58                  <1> 	pop	eax
  1967 00000BC6 5B                  <1> 	pop	ebx
  1968 00000BC7 1F                  <1> 	pop	ds
  1969 00000BC8 CF                  <1> 	iret
  1970                              <1> 
  1971                              <1> ; 18/02/2015
  1972                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1973                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1974                              <1> ; scancode and ascii code of the character 
  1975                              <1> ; in the tty input (ttychr) buffer. 
  1976                              <1> ; Test procedures must call 'getch' for tty input
  1977                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1978                              <1> ; due to infinite (key press) waiting loop.
  1979                              <1> ; 
  1980                              <1> ; 03/12/2014
  1981                              <1> ; 26/08/2014
  1982                              <1> ; KEYBOARD I/O
  1983                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1984                              <1> 
  1985                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1986                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1987                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1988                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1989                              <1> 
  1990                              <1> int_16h: ; 30/06/2015
  1991                              <1> ;getc:
  1992 00000BC9 9C                  <1> 	pushfd	; 28/08/2014
  1993 00000BCA 0E                  <1> 	push 	cs
  1994 00000BCB E826000000          <1> 	call 	getc_int
  1995 00000BD0 C3                  <1> 	retn
  1996                              <1> 
  1997                              <1> ; 24/12/2021
  1998                              <1> 
  1999                              <1> 	;-----	SHIFT STATUS
  2000                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2001 00000BD1 8A25[645D0000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2002 00000BD7 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2003                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2004                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2005 00000BDA C0E405              <1>         shl	ah, 5
  2006 00000BDD A0[645D0000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2007 00000BE2 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2008 00000BE4 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2009 00000BE6 A0[665D0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2010 00000BEB 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2011 00000BED 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2012                              <1> _K3:
  2013 00000BEF A0[635D0000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2014 00000BF4 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2015                              <1> 
  2016                              <1> getc_int:
  2017                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2018                              <1> 	; 28/02/2015
  2019                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2020                              <1> 	;	      instead of pc-at bios - 1985-)
  2021                              <1> 	; 28/08/2014 (_k1d)
  2022                              <1> 	; 30/06/2014
  2023                              <1> 	; 03/03/2014
  2024                              <1> 	; 28/02/2014
  2025                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2026                              <1> 	; rombios source code (21/04/1986)
  2027                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2028                              <1> 	;
  2029                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2030                              <1> 	;
  2031                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2032                              <1> 	; KEYBOARD I/O								      :
  2033                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2034                              <1> 	; INPUT									      :
  2035                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2036                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2037                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2038                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2039                              <1> 	;-----------------------------------------------------------------------------:
  2040                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2041                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2042                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2043                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2044                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2045                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2046                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2047                              <1> 	;-----------------------------------------------------------------------------:	
  2048                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2049                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2050                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2051                              <1> 	;-----------------------------------------------------------------------------:	
  2052                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2053                              <1> 	;	      (AL) = 05H                                                      :
  2054                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2055                              <1> 	;		       							      :
  2056                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2057                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2058                              <1> 	;                     --------------------------------------------            :
  2059                              <1> 	;			00H        30.0        10H        7.5                 :
  2060                              <1> 	;			01H        26.7        11H        6.7                 :
  2061                              <1> 	;			02H        24.0        12H        6.0                 :
  2062                              <1> 	;			03H        21.8        13H        5.5                 :
  2063                              <1> 	;			04H        20.0        14H        5.0                 :
  2064                              <1> 	;			05H        18.5        15H        4.6                 :
  2065                              <1> 	;			06H        17.1        16H        4.3                 :
  2066                              <1> 	;			07H        16.0        17H        4.0                 :
  2067                              <1> 	;			08H        15.0        18H        3.7                 :
  2068                              <1> 	;			09H        13.3        19H        3.3                 :
  2069                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2070                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2071                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2072                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2073                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2074                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2075                              <1> 	;									      :
  2076                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2077                              <1> 	;		       							      :
  2078                              <1> 	;                     REGISTER     DELAY                                      :
  2079                              <1> 	;                      VALUE       VALUE                                      :
  2080                              <1> 	;                     ------------------                                      :
  2081                              <1> 	;			00H        250 ms                                     :
  2082                              <1> 	;			01H        500 ms                                     :
  2083                              <1> 	;			02H        750 ms                                     :
  2084                              <1> 	;			03H       1000 ms                                     :
  2085                              <1> 	;-----------------------------------------------------------------------------:
  2086                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2087                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2088                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2089                              <1> 	;		           (CH) = SCAN CODE                                   :
  2090                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2091                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2092                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2093                              <1> 	;-----------------------------------------------------------------------------:		
  2094                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2095                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2096                              <1> 	;-----------------------------------------------------------------------------:
  2097                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2098                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2099                              <1> 	;-----------------------------------------------------------------------------:	
  2100                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2101                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2102                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2103                              <1> 	; OUTPUT					                              :
  2104                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2105                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2106                              <1> 	;------------------------------------------------------------------------------
  2107                              <1> 	
  2108 00000BF6 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2109 00000BF7 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2110 00000BF8 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2111                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2112 00000BF9 66BB1000            <1>         mov     bx, KDATA 
  2113 00000BFD 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2114 00000BFF 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2115 00000C01 742D                <1> 	jz	short _K1		; ASCII_READ
  2116 00000C03 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2117 00000C05 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2118 00000C07 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2119 00000C09 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2120 00000C0B FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2121 00000C0D 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2122 00000C0F 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2123 00000C12 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2124                              <1> _KIO1:	
  2125 00000C14 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2126 00000C17 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2127 00000C19 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2128 00000C1B 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2129 00000C1D FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2130 00000C1F 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2131                              <1> _KIO_EXIT:
  2132                              <1> 	;pop	ecx			; RECOVER REGISTER
  2133 00000C21 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2134 00000C22 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2135 00000C23 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2136                              <1> 
  2137                              <1> 	;-----	ASCII CHARACTER
  2138                              <1> _K1E:	
  2139 00000C24 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2140 00000C29 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2141 00000C2E EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2142                              <1> _K1:	
  2143 00000C30 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2144 00000C35 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2145 00000C3A 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2146                              <1> _K1A:
  2147 00000C3C EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2148                              <1> 
  2149                              <1> 	;-----	ASCII STATUS
  2150                              <1> _K2E:	
  2151 00000C3E E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2152 00000C43 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2153 00000C45 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2154 00000C46 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2155 00000C4B EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2156                              <1> _K2:	
  2157 00000C4D E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2158 00000C52 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2159 00000C54 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2160 00000C55 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2161 00000C5A 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2162 00000C5C 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2163 00000C5D E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2164 00000C62 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2165                              <1> _K2A:
  2166 00000C64 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2167                              <1> _K2B:
  2168                              <1> 	;pop	ecx			; RECOVER REGISTER
  2169 00000C65 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2170 00000C66 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2171 00000C67 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2172                              <1> 
  2173                              <1> ; 24/12/2021
  2174                              <1> ;	;-----	SHIFT STATUS
  2175                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2176                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2177                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2178                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2179                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2180                              <1> ;       shl	ah, 5
  2181                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2182                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2183                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2184                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2185                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2186                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2187                              <1> ;_K3:
  2188                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2189                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2190                              <1> 
  2191                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2192                              <1> _K300:
  2193 00000C6A 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2194 00000C6C 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2195 00000C6E F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2196 00000C71 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2197 00000C73 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2198 00000C76 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2199 00000C78 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2200 00000C7A E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2201                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2202                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2203 00000C7F C0E705              <1> 	shl	bh, 5
  2204 00000C82 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2205 00000C84 08F8                <1> 	or	al, bh			; AND DELAY
  2206 00000C86 E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2207 00000C8B EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2208                              <1> 
  2209                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2210                              <1> _K500:
  2211 00000C8D 56                  <1> 	push	esi			; SAVE SI (esi)
  2212 00000C8E FA                  <1> 	cli				; 
  2213 00000C8F 8B1D[745D0000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2214 00000C95 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2215 00000C97 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2216 00000C9C 3B1D[705D0000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2217 00000CA2 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2218 00000CA4 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2219 00000CA7 891D[745D0000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2220 00000CAD 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2221 00000CAF EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2222                              <1> _K502:
  2223 00000CB1 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2224                              <1> _K504:
  2225 00000CB3 FB                  <1> 	sti				
  2226 00000CB4 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2227 00000CB5 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2228                              <1> 
  2229                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2230                              <1> _K1S:
  2231 00000CBA FA                  <1> 	cli	; 03/12/2014
  2232 00000CBB 8B1D[705D0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2233 00000CC1 3B1D[745D0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2234                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2235 00000CC7 750F                <1> 	jne	short _k1x ; 03/12/2014
  2236                              <1> 	;
  2237                              <1> 	; 03/12/2014
  2238                              <1> 	; 28/08/2014
  2239                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2240                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2241                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2242                              <1> _K1T:                                   ; ASCII READ
  2243 00000CC9 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2244 00000CCA 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2245                              <1> _K1U:	
  2246 00000CCB FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2247 00000CCC 8B1D[705D0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2248 00000CD2 3B1D[745D0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2249                              <1> _k1x:
  2250 00000CD8 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2251 00000CD9 9C                  <1> 	pushf				; SAVE FLAGS
  2252 00000CDA E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2253 00000CDF 8A1D[655D0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2254 00000CE5 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2255 00000CE7 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2256 00000CEA 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2257 00000CEC E86A060000          <1> 	call	SND_LED1
  2258 00000CF1 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2259                              <1> _K1V:
  2260 00000CF2 9D                  <1> 	popf				; RESTORE FLAGS
  2261 00000CF3 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2262 00000CF4 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2263                              <1> 	;
  2264 00000CF6 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2265 00000CF9 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2266 00000CFE 891D[705D0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2267 00000D04 C3                  <1> 	retn				; RETURN
  2268                              <1> 
  2269                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2270                              <1> _K2S:
  2271 00000D05 FA                  <1> 	cli				; INTERRUPTS OFF
  2272 00000D06 8B1D[705D0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2273 00000D0C 3B1D[745D0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2274 00000D12 668B03              <1> 	mov	ax, [ebx]
  2275 00000D15 9C                  <1> 	pushf				; SAVE FLAGS
  2276                              <1> 	;push	ax			; SAVE CODE
  2277                              <1> 	; 24/12/2021
  2278 00000D16 50                  <1> 	push	eax
  2279 00000D17 E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2280 00000D1C 8A1D[655D0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2281 00000D22 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2282 00000D24 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2283 00000D27 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2284 00000D29 E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2285                              <1> _K2T:
  2286                              <1> 	;pop	ax			; RESTORE CODE
  2287                              <1> 	; 24/12/2021
  2288 00000D2E 58                  <1> 	pop	eax
  2289 00000D2F 9D                  <1> 	popf				; RESTORE FLAGS
  2290 00000D30 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2291 00000D31 C3                  <1> 	retn				; RETURN
  2292                              <1> 
  2293                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2294                              <1> _KIO_E_XLAT:
  2295 00000D32 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2296 00000D34 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2297 00000D36 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2298 00000D38 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2299 00000D3A 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2300                              <1> _KIO_E_RET:				
  2301 00000D3C C3                  <1> 	retn				; GO BACK
  2302                              <1> 
  2303                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2304                              <1> _KIO_S_XLAT:
  2305 00000D3D 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2306 00000D40 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2307 00000D42 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2308 00000D44 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2309 00000D46 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2310 00000D48 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2311 00000D4A B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2312                              <1> _kio_ret: ; 03/12/2014
  2313 00000D4C F8                  <1> 	clc
  2314 00000D4D C3                  <1> 	retn
  2315                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2316                              <1> _KIO_S1:				
  2317 00000D4E B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2318                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2319 00000D50 C3                  <1> 	retn
  2320                              <1> _KIO_S2:		
  2321 00000D51 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2322 00000D54 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2323 00000D56 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2324 00000D58 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2325 00000D5A 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2326 00000D5C 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2327 00000D5E EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2328                              <1> _KIO_S3:
  2329 00000D60 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2330                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2331 00000D62 75E8                <1> 	jne	short _kio_ret
  2332 00000D64 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2333 00000D66 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2334 00000D68 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2335                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2336                              <1> _KIO_USE:
  2337                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2338 00000D6A C3                  <1> 	retn				; RETURN	
  2339                              <1> _KIO_DIS:
  2340 00000D6B F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2341 00000D6C C3                  <1> 	retn				; RETURN
  2342                              <1> 
  2343                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2344                              <1> _K4:    
  2345 00000D6D 43                  <1> 	inc     ebx
  2346 00000D6E 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2347 00000D6F 3B1D[6C5D0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2348                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2349 00000D75 7206                <1> 	jb	short _K5
  2350 00000D77 8B1D[685D0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2351                              <1> _K5:
  2352 00000D7D C3                  <1> 	retn
  2353                              <1> 
  2354                              <1> ; 20/02/2015
  2355                              <1> ; 05/12/2014
  2356                              <1> ; 26/08/2014
  2357                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2358                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2359                              <1> ;
  2360                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2361                              <1> ; rombios source code (06/10/1985)
  2362                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2363                              <1> 
  2364                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2365                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2366                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2367                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2368                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2369                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2370                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2371                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2372                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2373                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2374                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2375                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2376                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2377                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2378                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2379                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2380                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2381                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2382                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2383                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2384                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2385                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2386                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2387                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2388                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2389                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2390                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2391                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2392                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2393                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2394                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2395                              <1> F11_M		equ	87		; F11 KEY MAKE
  2396                              <1> F12_M		equ	88		; F12 KEY MAKE
  2397                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2398                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2399                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2400                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2401                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2402                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2403                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2404                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2405                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2406                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2407                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2408                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2409                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2410                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2411                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2412                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2413                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2414                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2415                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2416                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2417                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2418                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2419                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2420                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2421                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2422                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2423                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2424                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2425                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2426                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2427                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2428                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2429                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2430                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2431                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2432                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2433                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2434                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2435                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2436                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2437                              <1> ;
  2438                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2439                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2440                              <1> INTA00		equ	020h		; 8259 PORT
  2441                              <1> 
  2442                              <1> 
  2443                              <1> kb_int:
  2444                              <1> 
  2445                              <1> ; 13/06/2022
  2446                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2447                              <1> ; 17/10/2015 ('ctrlbrk') 
  2448                              <1> ; 05/12/2014
  2449                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2450                              <1> 	;	      instead of pc-at bios - 1985-)
  2451                              <1> ; 26/08/2014
  2452                              <1> ;
  2453                              <1> ; 03/06/86  KEYBOARD BIOS
  2454                              <1> ;
  2455                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2456                              <1> ;										;
  2457                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2458                              <1> ;										;
  2459                              <1> ;--------------------------------------------------------------------------------
  2460                              <1> 
  2461                              <1> KB_INT_1:
  2462 00000D7E FB                  <1> 	sti				; ENABLE INTERRUPTS
  2463                              <1> 	;push	ebp
  2464 00000D7F 50                  <1> 	push	eax
  2465 00000D80 53                  <1> 	push	ebx
  2466 00000D81 51                  <1> 	push	ecx
  2467 00000D82 52                  <1> 	push	edx
  2468 00000D83 56                  <1> 	push	esi
  2469 00000D84 57                  <1> 	push	edi
  2470 00000D85 1E                  <1> 	push	ds
  2471 00000D86 06                  <1> 	push	es
  2472 00000D87 FC                  <1> 	cld				; FORWARD DIRECTION
  2473 00000D88 66B81000            <1> 	mov	ax, KDATA
  2474 00000D8C 8ED8                <1> 	mov	ds, ax
  2475 00000D8E 8EC0                <1> 	mov	es, ax
  2476                              <1> 	;
  2477                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2478 00000D90 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2479 00000D92 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2480 00000D97 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2481 00000D98 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2482                              <1> KB_INT_01:
  2483 00000D9D E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2484 00000D9F A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2485 00000DA1 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2486                              <1> 	;
  2487                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2488 00000DA3 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2489                              <1> 	;
  2490                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2491                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2492                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2493                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2494                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2495                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2496                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2497                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2498                              <1> 	;
  2499                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2500                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2501 00000DA5 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2502 00000DA6 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2503 00000DA8 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2504                              <1> 	;
  2505                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2506 00000DAA 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2507 00000DAC 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2508                              <1> 	;
  2509                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2510 00000DAE FA                  <1> 	cli				; DISABLE INTERRUPTS
  2511 00000DAF 800D[655D0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2512 00000DB6 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2513                              <1> 	;
  2514                              <1> 	;-----	RESEND THE LAST BYTE
  2515                              <1> KB_INT_4:
  2516 00000DBB FA                  <1> 	cli				; DISABLE INTERRUPTS
  2517 00000DBC 800D[655D0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2518 00000DC3 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2519                              <1> 	;
  2520                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2521                              <1> KB_INT_2:
  2522                              <1> 	;push 	ax			; SAVE DATA IN
  2523                              <1> 	; 24/12/2021
  2524 00000DC8 50                  <1> 	push	eax
  2525 00000DC9 E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2526 00000DCE 8A1D[655D0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2527 00000DD4 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2528 00000DD6 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2529 00000DD9 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2530 00000DDB E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2531                              <1> UP0:
  2532                              <1> 	;pop	ax			; RESTORE DATA IN
  2533                              <1> 	; 24/12/2021
  2534 00000DE0 58                  <1> 	pop	eax
  2535                              <1> ;------------------------------------------------------------------------
  2536                              <1> ;	START OF KEY PROCESSING						;
  2537                              <1> ;------------------------------------------------------------------------
  2538 00000DE1 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2539                              <1> 	;
  2540                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2541 00000DE3 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2542                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2543                              <1> 	; 24/12/2021
  2544 00000DE5 7505                <1> 	jne	short K16
  2545 00000DE7 E9E9040000          <1> 	jmp	K62
  2546                              <1> K16:	
  2547 00000DEC 8A3D[665D0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2548                              <1> 	;
  2549                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2550 00000DF2 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2551 00000DF5 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2552 00000DF7 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2553 00000DF9 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2554 00000DFB 7507                <1> 	jne	short RST_RD_ID
  2555 00000DFD 800D[665D0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2556                              <1> RST_RD_ID:
  2557 00000E04 8025[665D0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2558 00000E0B EB27                <1>         jmp    short ID_EX		; AND EXIT
  2559                              <1> 	; 24/12/2021
  2560                              <1> 	;jmp	K26
  2561                              <1> 	;
  2562                              <1> TST_ID_2:
  2563 00000E0D 8025[665D0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2564 00000E14 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2565 00000E16 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2566 00000E18 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2567 00000E1A 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2568                              <1> 	; 24/12/2021
  2569                              <1> 	;jne	K26
  2570                              <1> 	;
  2571                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2572 00000E1C F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2573 00000E1F 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2574 00000E21 800D[635D0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2575 00000E28 E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2576                              <1> KX_BIT:
  2577 00000E2D 800D[665D0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2578 00000E34 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2579                              <1> 	;
  2580                              <1> NOT_ID:
  2581 00000E39 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2582 00000E3B 750E                <1> 	jne	short TEST_E1
  2583 00000E3D 800D[665D0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2584 00000E44 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2585                              <1> 	; 24/12/2021
  2586 00000E46 E9DA010000          <1> 	jmp	K26A	
  2587                              <1> TEST_E1:	
  2588 00000E4B 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2589 00000E4D 750C                <1> 	jne	short NOT_HC
  2590 00000E4F 800D[665D0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2591 00000E56 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2592                              <1> 	;
  2593                              <1> NOT_HC:
  2594 00000E5B 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2595 00000E5D F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2596 00000E60 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2597                              <1> 	;
  2598 00000E62 BF[4E5C0000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2599 00000E67 AE                  <1> 	scasb
  2600                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2601                              <1> 	; 24/12/2021
  2602 00000E68 7458                <1> 	je	short K16B
  2603 00000E6A AE                  <1> 	scasb
  2604 00000E6B 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2605 00000E6D EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2606                              <1> 	; 24/12/2021
  2607                              <1> 	;jmp	K26
  2608                              <1> 	;
  2609                              <1> NOT_LC_E0:
  2610 00000E6F F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2611 00000E72 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2612 00000E74 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2613 00000E79 BF[4C5C0000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2614 00000E7E F2AE                <1> 	repne	scasb			; CHECK IT
  2615 00000E80 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2616                              <1> 	; 24/12/2021
  2617                              <1> 	;je	K26A			
  2618                              <1> 	;
  2619 00000E82 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2620 00000E84 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2621                              <1> 	; 24/12/2021
  2622                              <1> 	;jne	K26
  2623 00000E86 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2624 00000E89 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2625                              <1> 	; 24/12/2021
  2626                              <1> 	;jnz	K26
  2627                              <1>         ; 20/02/2015 
  2628 00000E8B F605[645D0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2629 00000E92 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2630                              <1> 	; 24/12/2021
  2631                              <1> 	;jnz	K26
  2632 00000E94 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2633                              <1> 	;
  2634                              <1> 	;-----	TEST FOR SYSTEM KEY
  2635                              <1> T_SYS_KEY:
  2636 00000E99 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2637 00000E9B 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2638                              <1> 	;
  2639 00000E9D F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2640 00000EA0 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2641                              <1> 	;
  2642 00000EA2 F605[645D0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2643 00000EA9 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2644                              <1> 	;jnz	K26			
  2645                              <1> 	;
  2646 00000EAB 800D[645D0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2647 00000EB2 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2648 00000EB4 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2649                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2650 00000EB6 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2651 00000EB8 E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2652                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2653                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2654                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2655                              <1> 	;INT	15H			; USER INTERRUPT	
  2656 00000EBD E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2657                              <1> 	;
  2658 00000EC2 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2659                              <1> 	;
  2660                              <1> K16C:
  2661 00000EC7 8025[645D0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2662 00000ECE B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2663 00000ED0 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2664                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2665                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2666                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2667                              <1> 	;
  2668                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2669                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2670                              <1> 	;INT	15H			; USER INTERRUPT
  2671                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2672                              <1> 	;
  2673 00000ED2 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2674                              <1> 	;
  2675                              <1> 	;-----	TEST FOR SHIFT KEYS
  2676                              <1> K16A:
  2677 00000ED7 8A1D[635D0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2678 00000EDD BF[485C0000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2679 00000EE2 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2680 00000EE7 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2681 00000EE9 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2682                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2683                              <1> 	; 24/12/2021
  2684 00000EEB 7405                <1> 	je	short K17
  2685 00000EED E914010000          <1> 	jmp	K25
  2686                              <1> 	;
  2687                              <1> 	;------	SHIFT KEY FOUND
  2688                              <1> K17:
  2689 00000EF2 81EF[495C0000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2690 00000EF8 8AA7[505C0000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2691 00000EFE B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2692 00000F00 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2693                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2694                              <1> 	; 24/12/2021
  2695 00000F02 7405                <1> 	jz	short K17C
  2696 00000F04 E999000000          <1> 	jmp	K23
  2697                              <1> 	;
  2698                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2699                              <1> K17C:
  2700 00000F09 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2701 00000F0C 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2702                              <1> 	;
  2703                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2704 00000F0E 0825[635D0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2705 00000F14 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2706 00000F16 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2707                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2708                              <1> 	; 24/12/2021
  2709 00000F18 E901010000          <1> 	jmp	K26
  2710                              <1> K17D:
  2711 00000F1D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2712 00000F20 740B                <1> 	jz 	short K17E		; NO, JUMP
  2713 00000F22 0825[665D0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2714 00000F28 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2715                              <1> K17E:
  2716 00000F2D D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2717 00000F2F 0825[645D0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2718 00000F35 E9E4000000          <1> 	jmp	K26
  2719                              <1> 	;
  2720                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2721                              <1> K18:					; SHIFT-TOGGLE
  2722 00000F3A F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2723 00000F3D 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2724                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2725                              <1> 	; 24/12/2021
  2726 00000F3F E9C2000000          <1> 	jmp	K25
  2727                              <1> K18A:
  2728 00000F44 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2729 00000F46 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2730 00000F48 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2731 00000F4B 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2732                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2733                              <1> 	; 24/12/2021
  2734 00000F4D E9B4000000          <1> 	jmp	K25
  2735                              <1> K18B:
  2736 00000F52 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2737 00000F55 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2738                              <1> K19:	
  2739 00000F57 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2740 00000F5A 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2741 00000F5C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2742 00000F5F 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2743                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2744 00000F61 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2745 00000F63 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2746                              <1> K21:					; MIGHT BE NUMERIC
  2747 00000F68 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2748 00000F6B 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2749                              <1> 	;
  2750                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2751 00000F6D 8425[645D0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2752                              <1> 	;jnz	K26
  2753                              <1> 	; 24/12/2021
  2754 00000F73 7405                <1> 	jz	short K22A
  2755 00000F75 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2756                              <1> K22A:
  2757 00000F7A 0825[645D0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2758 00000F80 3025[635D0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2759                              <1> 	;
  2760                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2761 00000F86 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2762 00000F89 7407                <1> 	jz	short K22B		; GO IF NOT
  2763                              <1> 	;
  2764                              <1> 	; 24/12/2021
  2765                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2766 00000F8B 50                  <1> 	push	eax
  2767 00000F8C E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2768                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2769 00000F91 58                  <1> 	pop	eax
  2770                              <1> K22B:
  2771 00000F92 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2772                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2773                              <1> 	; 24/12/2021
  2774 00000F94 7405                <1> 	je	short K22C
  2775 00000F96 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2776                              <1> K22C:
  2777 00000F9B 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2778 00000F9D E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2779                              <1> 	;
  2780                              <1> 	;-----	BREAK SHIFT FOUND
  2781                              <1> K23:					; BREAK-SHIFT-FOUND
  2782 00000FA2 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2783 00000FA5 F6D4                <1> 	not	ah			; INVERT MASK
  2784 00000FA7 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2785 00000FA9 2025[635D0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2786 00000FAF 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2787 00000FB2 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2788                              <1> 	;
  2789 00000FB4 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2790 00000FB7 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2791 00000FB9 2025[665D0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2792 00000FBF EB08                <1> 	jmp	short K23B		; CONTINUE
  2793                              <1> K23A:
  2794 00000FC1 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2795 00000FC3 2025[645D0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2796                              <1> K23B:
  2797 00000FC9 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2798 00000FCB A0[665D0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2799 00000FD0 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2800 00000FD2 0A05[645D0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2801 00000FD8 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2802 00000FDA 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2803 00000FDC 0805[635D0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2804 00000FE2 88E0                <1> 	mov	al, ah
  2805                              <1> K23D:
  2806 00000FE4 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2807 00000FE6 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2808                              <1> 	;	
  2809                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2810 00000FE8 A0[675D0000]        <1> 	mov	al, [ALT_INPUT]
  2811 00000FED B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2812 00000FEF 8825[675D0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2813 00000FF5 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2814 00000FF7 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2815 00000FF9 E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2816                              <1> 	;
  2817                              <1> K24:					; BREAK-TOGGLE
  2818 00000FFE 2025[645D0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2819 00001004 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2820                              <1> 	;
  2821                              <1> 	;-----	TEST FOR HOLD STATE
  2822                              <1> 					; AL, AH = SCAN CODE
  2823                              <1> K25:					; NO-SHIFT-FOUND
  2824 00001006 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2825 00001008 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2826 0000100A F605[645D0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2827 00001011 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2828 00001013 3C45                <1> 	cmp	al, NUM_KEY
  2829 00001015 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2830 00001017 8025[645D0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2831                              <1> 	;
  2832                              <1> K26:
  2833 0000101E 8025[665D0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2834                              <1> K26A:					; INTERRUPT-RETURN
  2835 00001025 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2836 00001026 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2837 00001028 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2838                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2839 0000102A B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2840 0000102C E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2841                              <1> K27A:
  2842 00001031 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2843 00001032 07                  <1> 	pop	es			; RESTORE REGISTERS
  2844 00001033 1F                  <1> 	pop	ds
  2845 00001034 5F                  <1> 	pop	edi
  2846 00001035 5E                  <1> 	pop	esi
  2847 00001036 5A                  <1> 	pop	edx
  2848 00001037 59                  <1> 	pop	ecx
  2849 00001038 5B                  <1> 	pop	ebx
  2850 00001039 58                  <1> 	pop	eax
  2851                              <1> 	;pop	ebp
  2852 0000103A CF                  <1> 	iret				; RETURN
  2853                              <1> 
  2854                              <1> 	;-----	NOT IN	HOLD STATE
  2855                              <1> K28:					; NO-HOLD-STATE
  2856 0000103B 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2857 0000103D 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2858                              <1> 	;
  2859 0000103F F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2860 00001042 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2861                              <1>         ; 24/12/2021
  2862                              <1> 	;jz      K38
  2863                              <1> 	;
  2864 00001044 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2865 00001047 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2866                              <1> 	; 28/02/2015
  2867 00001049 F605[645D0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2868 00001050 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2869                              <1> 	; 24/12/2021
  2870                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2871                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2872 00001052 E9CD000000          <1> K28A:	jmp	K38
  2873                              <1> 	;
  2874                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2875                              <1> K29:					; TEST-RESET
  2876 00001057 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2877 0000105A 740B                <1> 	jz	short K31		; NO_RESET
  2878 0000105C 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2879 0000105E 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2880                              <1> 	;
  2881                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2882                              <1>  	; 26/08/2014
  2883                              <1> cpu_reset:
  2884                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2885                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2886 00001060 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2887 00001062 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2888                              <1> khere:
  2889 00001064 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2890 00001065 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2891                              <1> 
  2892                              <1> 	;
  2893                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2894                              <1> K31:					; NO-RESET
  2895 00001067 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2896 00001069 7507                <1> 	jne	short K311		; NOT THERE
  2897 0000106B B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2898 0000106D E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2899                              <1> K311:
  2900 00001072 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2901 00001074 7509                <1> 	jne	short K312		; NOT THERE
  2902 00001076 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2903 0000107A E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2904                              <1> K312:
  2905 0000107F 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2906 00001081 7471                <1>         je	short K37B              ; GO PROCESS
  2907 00001083 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2908 00001085 746D                <1>         je	short K37B              ; GO PROCESS
  2909                              <1> 	;
  2910                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2911                              <1> K32:					; ALT-KEY-PAD
  2912 00001087 BF[245C0000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2913 0000108C B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2914 00001091 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2915 00001093 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2916 00001095 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2917                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2918                              <1> 	; 24/12/2021
  2919 00001098 751C                <1> 	jnz	short K32B
  2920 0000109A 81EF[255C0000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2921 000010A0 A0[675D0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2922 000010A5 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2923 000010A7 F6E4                <1> 	mul	ah
  2924 000010A9 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2925 000010AC A2[675D0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2926                              <1> K32A:
  2927 000010B1 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2928                              <1> K32B:
  2929                              <1> 	; 24/12/2021
  2930 000010B6 EB66                <1> 	jmp	K37C
  2931                              <1> 	;
  2932                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2933                              <1> K33:					; NO-ALT-KEYPAD
  2934 000010B8 C605[675D0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2935 000010BF B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2936 000010C4 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2937 000010C6 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2938                              <1> 	;
  2939                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2940                              <1> K34:					; ALT-TOP-ROW
  2941 000010C8 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2942 000010CA 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2943 000010CC 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2944 000010CE 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2945 000010D0 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2946 000010D3 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2947                              <1> 	;
  2948                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2949                              <1> K35:					; ALT-FUNCTION
  2950 000010D5 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2951 000010D7 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2952 000010D9 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2953 000010DB 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2954 000010DD 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2955 000010E0 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2956                              <1> K35A:
  2957 000010E2 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2958 000010E5 7425                <1> 	jz	short K37		; NO, JUMP
  2959 000010E7 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2960 000010E9 7510                <1>         jne     short K35B              ; NOT THERE
  2961 000010EB 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2962 000010EF E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  2963                              <1> K37B:
  2964 000010F4 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2965 000010F6 E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2966                              <1> K35B:
  2967 000010FB 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2968 000010FD 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2969 000010FF 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2970 00001101 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2971                              <1>         ; 24/12/2021
  2972                              <1> 	;jne	K26
  2973 00001103 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2974 00001107 E998010000          <1> 	jmp	K57			; BUFFER FILL
  2975                              <1> K37:
  2976 0000110C 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2977 0000110E 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2978 00001110 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2979 00001112 779D                <1>         ja	short K32A		; IF SO, IGNORE
  2980                              <1> 	; 13/06/2022
  2981                              <1>         ;ja	K26
  2982 00001114 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2983                              <1> K37A:
  2984 00001117 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2985 00001119 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2986                              <1> K37C:
  2987 0000111E 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2988 00001120 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2989 00001122 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2990                              <1> 	;
  2991                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2992                              <1> K38:					; NOT-ALT-SHIFT
  2993                              <1> 					; BL STILL HAS SHIFT FLAGS
  2994 00001124 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2995 00001127 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2996                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2997                              <1> 	; 24/12/2021
  2998 00001129 E9AB000000          <1> 	jmp	K44
  2999                              <1> 	;
  3000                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3001                              <1> 	;-----	TEST FOR BREAK
  3002                              <1> K38A:
  3003 0000112E 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3004 00001130 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3005 00001132 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3006 00001135 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3007 00001137 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3008 0000113A 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3009                              <1> K38B:
  3010 0000113C 8B1D[705D0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3011 00001142 891D[745D0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3012 00001148 C605[625D0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3013                              <1> 	;
  3014                              <1> 	;-----	ENABLE KEYBOARD
  3015 0000114F B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3016 00001151 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3017                              <1> 	;
  3018                              <1> 	; CTRL+BREAK code here !!!
  3019                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3020                              <1> 	; 17/10/2015	
  3021 00001156 E8A6190000          <1> 	call	ctrlbrk ; control+break subroutine
  3022                              <1> 	;
  3023                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3024                              <1> 	; 24/12/2021
  3025 0000115B 29C0                <1> 	sub	eax, eax
  3026 0000115D E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3027                              <1> 	;
  3028                              <1> 	;-----	TEST FOR PAUSE
  3029                              <1> K39:					; NO_BREAK
  3030 00001162 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3031 00001165 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3032 00001167 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3033 00001169 7533                <1> 	jne	short K41		; NO-PAUSE
  3034                              <1> K39P:
  3035 0000116B 800D[645D0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3036                              <1> 	;
  3037                              <1> 	;-----	ENABLE KEYBOARD
  3038 00001172 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3039 00001174 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3040                              <1> K39A:
  3041 00001179 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3042 0000117B E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3043                              <1> 	;
  3044                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3045 0000117D 803D[605D0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3046 00001184 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3047 00001186 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3048 0000118A A0[615D0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3049 0000118F EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3050                              <1> 	;
  3051                              <1> K40:					; PAUSE-LOOP
  3052 00001190 F605[645D0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3053 00001197 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3054                              <1> 	;
  3055 00001199 E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3056                              <1>         ;
  3057                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3058                              <1> K41:					; NO-PAUSE
  3059 0000119E 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3060 000011A0 7513                <1> 	jne	short K42		; NOT-KEY-55
  3061 000011A2 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3062 000011A5 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3063 000011A7 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3064 000011AA 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3065                              <1> K41A:	
  3066 000011AC 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3067 000011B0 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3068                              <1> 	;
  3069                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3070                              <1> K42:					; NOT-KEY-55
  3071 000011B5 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3072 000011B7 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3073 000011B9 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3074 000011BB 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3075 000011BD F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3076 000011C0 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3077 000011C2 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3078 000011C6 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3079                              <1> K42A:
  3080                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3081 000011CB 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3082                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3083                              <1> 	;;jb	K56 ; 20/02/2015
  3084                              <1> 	;;jmp	K64 ; 20/02/2015
  3085                              <1> K42B:
  3086 000011CD BB[585C0000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3087                              <1> 	;;jmp	K64
  3088                              <1> 	;jb	K56 ;; 20/02/2015	
  3089                              <1> 	; 24/12/2021
  3090 000011D2 7267                <1> 	jb	short K45F
  3091 000011D4 E9B9000000          <1> 	jmp	K64	
  3092                              <1>         ;
  3093                              <1> 	;-----	NOT IN CONTROL SHIFT
  3094                              <1> K44:					; NOT-CTL-SHIFT
  3095 000011D9 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3096 000011DB 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3097 000011DD F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3098 000011E0 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3099 000011E2 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3100 000011E5 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3101 000011E7 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3102                              <1> K44A:
  3103 000011E9 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3104 000011EC 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3105                              <1> 	;
  3106                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3107                              <1> K44B:
  3108 000011EE B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3109 000011F0 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3110 000011F5 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3111 000011F7 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3112                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3113                              <1> 	;PUSH 	BP			; SAVE POINTER
  3114                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3115                              <1> 	;POP	BP			; RESTORE POINTER
  3116 000011F9 8025[665D0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3117 00001200 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3118                              <1> 	;
  3119                              <1> 	;-----	HANDLE IN-CORE KEYS
  3120                              <1> K45:					; NOT-PRINT-SCREEN
  3121 00001205 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3122 00001207 7734                <1> 	ja	short K46		; JUMP IF NOT
  3123 00001209 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3124 0000120B 7505                <1> 	jne	short K45A		; NO, JUMP
  3125 0000120D F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3126 00001210 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3127                              <1> K45A:
  3128 00001212 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3129 00001217 BF[2E5C0000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3130 0000121C F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3131                              <1> 		; 20/02/2015
  3132 0000121E 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3133                              <1> 	;
  3134 00001220 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3135 00001223 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3136                              <1> K45B:
  3137 00001225 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3138 00001228 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3139                              <1> 					; NO, LOWERCASE
  3140                              <1> K45C:
  3141 0000122A BB[B05C0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3142 0000122F EB51                <1> 	jmp	short K56	
  3143                              <1> K45D:					; ALMOST-CAPS-STATE
  3144 00001231 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3145 00001234 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3146                              <1> K45E:
  3147 00001236 BB[085D0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3148 0000123B EB45                <1> K45F:	jmp	short K56
  3149                              <1> 	;
  3150                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3151                              <1> K46:					; NOT IN-CORE AREA
  3152 0000123D 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3153                              <1> 	;ja	short K47		; JUMP IF NOT
  3154                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3155 0000123F 7635                <1> 	jna	short K53		
  3156                              <1> 	;
  3157                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3158                              <1> K47:					; NOT F1 - F10
  3159 00001241 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3160 00001243 772D                <1> 	ja	short K52		; JUMP IF NOT
  3161                              <1> 	;
  3162                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3163                              <1> K48:
  3164 00001245 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3165 00001247 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3166 00001249 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3167 0000124B 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3168 0000124D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3169 00001250 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3170                              <1> 	;		
  3171 00001252 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3172 00001255 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3173 00001257 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3174                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3175 0000125A 75DA                <1> 	jnz	short K45E
  3176                              <1> 	;
  3177                              <1> 	;-----	BASE CASE FOR KEYPAD
  3178                              <1> K49:					
  3179 0000125C 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3180 0000125E 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3181 00001260 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3182 00001262 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3183                              <1> K49A:
  3184 00001264 BB[B05C0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3185 00001269 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3186                              <1> 	;
  3187                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3188                              <1> K50:					; ALMOST-NUM-STATE
  3189 0000126B F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3190 0000126E 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3191 00001270 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3192                              <1> 	;
  3193                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3194                              <1> K52:					; NOT A NUMPAD KEY
  3195 00001272 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3196                              <1> 	;jne	short K53		; JUMP IF NOT
  3197                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3198 00001274 74AF                <1> 	je	short K45B		
  3199                              <1> 	;
  3200                              <1> 	;-----	MUST BE F11 OR F12 
  3201                              <1> K53:					; F1 - F10 COME HERE, TOO
  3202 00001276 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3203 00001279 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3204                              <1> 		; 20/02/2015 
  3205 0000127B BB[085D0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3206 00001280 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3207                              <1> 	;
  3208                              <1> 	;-----	TRANSLATE THE CHARACTER
  3209                              <1> K56:					; TRANSLATE-CHAR
  3210 00001282 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3211 00001284 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3212 00001285 F605[665D0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3213 0000128C 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3214 0000128E B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3215 00001290 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3216                              <1> 	;
  3217                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3218                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3219 00001292 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3220 00001294 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3221 00001295 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3222 00001297 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3223 00001299 F605[665D0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3224 000012A0 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3225 000012A2 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3226                              <1> 	;
  3227                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3228                              <1> K57:					; BUFFER_FILL
  3229 000012A4 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3230 000012A6 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3231                              <1> 	; 24/12/2021
  3232                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3233 000012A8 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3234                              <1> 	; 24/12/2021
  3235 000012AB 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3236                              <1> 	;je	K26			; INTERRUPT_RETURN
  3237                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3238 000012AD E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3239                              <1> K61:					; NOT-CAPS-STATE
  3240 000012B2 8B1D[745D0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3241 000012B8 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3242 000012BA E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3243 000012BF 3B1D[705D0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3244 000012C5 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3245 000012C7 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3246 000012CA 891D[745D0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3247 000012D0 E949FDFFFF          <1> 	jmp	K26
  3248                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3249                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3250                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3251                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3252                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3253                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3254                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3255                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3256                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3257                              <1> 	;;jmp   K27                    
  3258                              <1> 	;
  3259                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3260                              <1> K62:
  3261 000012D5 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3262 000012D7 E620                <1> 	out	INTA00, al
  3263 000012D9 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3264 000012DD B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3265 000012DF E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3266 000012E4 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3267                              <1> 
  3268                              <1> SHIP_IT:
  3269                              <1> 	;---------------------------------------------------------------------------------
  3270                              <1> 	; SHIP_IT
  3271                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3272                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3273                              <1> 	;---------------------------------------------------------------------------------
  3274                              <1> 	;
  3275                              <1> 	;push	ax			; SAVE DATA TO SEND
  3276                              <1> 	; 24/12/2021
  3277 000012E9 50                  <1> 	push	eax
  3278                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3279 000012EA FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3280                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3281 000012EB B900000100          <1> 	mov	ecx, 10000h			
  3282                              <1> S10:
  3283 000012F0 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3284 000012F2 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3285 000012F4 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3286                              <1> 
  3287                              <1> 	;pop	ax			; GET DATA TO SEND
  3288                              <1> 	; 24/12/2021
  3289 000012F6 58                  <1> 	pop	eax
  3290 000012F7 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3291 000012F9 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3292 000012FA C3                  <1> 	retn				; RETURN TO CALLER
  3293                              <1> 
  3294                              <1> SND_DATA:
  3295                              <1> 	; ---------------------------------------------------------------------------------
  3296                              <1> 	; SND_DATA
  3297                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3298                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3299                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3300                              <1> 	; ---------------------------------------------------------------------------------
  3301                              <1> 	;
  3302                              <1> 	;push	ax			; SAVE REGISTERS
  3303                              <1> 	;push	bx
  3304                              <1> 	; 24/12/2021
  3305 000012FB 50                  <1> 	push	eax
  3306 000012FC 53                  <1> 	push	ebx
  3307 000012FD 51                  <1> 	push	ecx
  3308 000012FE 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3309 00001300 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3310                              <1> SD0:
  3311 00001302 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3312 00001303 8025[655D0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3313                              <1> 	;
  3314                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3315 0000130A B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3316                              <1> SD5:
  3317 0000130F E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3318 00001311 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3319 00001313 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3320                              <1> 	;
  3321 00001315 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3322 00001317 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3323 00001319 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3324                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3325 0000131A B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3326                              <1> SD1:
  3327 0000131F F605[655D0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3328 00001326 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3329 00001328 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3330                              <1> SD2:
  3331 0000132A FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3332 0000132C 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3333 0000132E 800D[655D0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3334 00001335 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3335                              <1> SD3:
  3336 00001337 F605[655D0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3337 0000133E 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3338                              <1> SD4:	
  3339 00001340 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3340                              <1> 	;pop	bx
  3341                              <1> 	;pop	ax
  3342                              <1> 	; 24/12/2021
  3343 00001341 5B                  <1> 	pop	ebx
  3344 00001342 58                  <1> 	pop	eax
  3345 00001343 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3346                              <1> 
  3347                              <1> SND_LED:
  3348                              <1> 	; ---------------------------------------------------------------------------------
  3349                              <1> 	; SND_LED
  3350                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3351                              <1> 	;
  3352                              <1> 	;----------------------------------------------------------------------------------
  3353                              <1> 	;
  3354 00001344 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3355 00001345 F605[655D0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3356 0000134C 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3357                              <1> 	;
  3358 0000134E 800D[655D0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3359 00001355 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3360 00001357 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3361 00001359 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3362                              <1> SND_LED1:
  3363 0000135B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3364 0000135C F605[655D0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3365 00001363 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3366                              <1> 	;
  3367 00001365 800D[655D0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3368                              <1> SL0:
  3369 0000136C B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3370 0000136E E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3371 00001373 FA                  <1> 	cli
  3372 00001374 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3373 00001379 8025[655D0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3374 00001380 0805[655D0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3375 00001386 F605[655D0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3376 0000138D 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3377                              <1> 	;
  3378 0000138F E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3379 00001394 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3380 00001395 F605[655D0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3381 0000139C 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3382                              <1> SL2:
  3383 0000139E B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3384 000013A0 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3385 000013A5 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3386                              <1> SL3:
  3387 000013A6 8025[655D0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3388                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3389 000013AD FB                  <1> 	sti				; ENABLE INTERRUPTS
  3390 000013AE C3                  <1> 	retn				; RETURN TO CALLER
  3391                              <1> 
  3392                              <1> MAKE_LED:
  3393                              <1> 	;---------------------------------------------------------------------------------
  3394                              <1> 	; MAKE_LED
  3395                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3396                              <1> 	;	THE MODE INDICATORS.
  3397                              <1> 	;---------------------------------------------------------------------------------
  3398                              <1> 	;
  3399                              <1> 	;push 	cx			; SAVE CX
  3400 000013AF A0[635D0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3401 000013B4 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3402                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3403                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3404 000013B6 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3405 000013B9 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3406                              <1> 	;pop	cx
  3407 000013BB C3                  <1> 	retn				; RETURN TO CALLER
  3408                              <1> 
  3409                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3410                              <1> 
  3411                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1831                                  
  1832                                  %include 'video.inc' ; 07/03/2015
  1833                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - VIDEO.INC
  1834                              <1> ; Last Modification: 14/06/2022
  1835                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1836                              <1> ;
  1837                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1838                              <1> 
  1839                              <1> ; 14/06/2022
  1840                              <1> ; 25/02/2022
  1841                              <1> ; 02/02/2022 (simplified scroll up)
  1842                              <1> ; 16/01/2016
  1843                              <1> ; 30/06/2015
  1844                              <1> ; 27/06/2015
  1845                              <1> ; 11/03/2015
  1846                              <1> ; 02/09/2014
  1847                              <1> ; 30/08/2014
  1848                              <1> ; VIDEO FUNCTIONS
  1849                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1850                              <1> 
  1851                              <1> write_tty:
  1852                              <1> 	; 02/02/2022
  1853                              <1> 	; 13/08/2015
  1854                              <1> 	; 02/09/2014
  1855                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1856                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1857                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1858                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1859                              <1> 	;
  1860                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1861                              <1> 	;	   AL = Character to be written
  1862                              <1> 	;	   EBX = Video Page (0 to 7)
  1863                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1864                              <1> 
  1865                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1866                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1867                              <1> 
  1868                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1869                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1870                              <1> ;
  1871                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1872                              <1> ;
  1873                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1874                              <1> ;										:
  1875                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1876                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1877                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1878                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1879                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1880                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1881                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1882                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1883                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1884                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1885                              <1> ;   THE 0 COLOR IS USED.							:
  1886                              <1> ;   ENTRY --									:
  1887                              <1> ;     (AH) = CURRENT CRT MODE							:
  1888                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1889                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1890                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1891                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1892                              <1> ;   EXIT -- 									:
  1893                              <1> ;     ALL REGISTERS SAVED							:
  1894                              <1> ;--------------------------------------------------------------------------------
  1895                              <1> 
  1896 000013BC FA                  <1> 	cli
  1897                              <1> 	;
  1898                              <1> 	; READ CURSOR (04/12/2013)
  1899                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1900 000013BD 08FF                <1> 	or	bh, bh
  1901                              <1> 	;jnz	beeper
  1902                              <1> 	; 02/02/2022
  1903 000013BF 7405                <1> 	jz	short u14
  1904 000013C1 E992000000          <1> 	jmp	beeper
  1905                              <1> u14:
  1906                              <1> 	; 02/02/2022
  1907                              <1> 	;; 01/09/2014
  1908                              <1> 	;cmp	byte [CRT_MODE], 3
  1909                              <1> 	;je	short m3
  1910                              <1> 	;;
  1911                              <1> 	;call	set_mode
  1912                              <1> m3:
  1913 000013C6 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1914                              <1> 	;shl	si, 1
  1915                              <1> 	; 02/02/2022
  1916 000013C8 D1E6                <1> 	shl	esi, 1
  1917 000013CA 81C6[26630000]      <1> 	add	esi, cursor_posn
  1918 000013D0 668B16              <1> 	mov	dx, [esi]
  1919                              <1> 	;
  1920                              <1> 	; dx now has the current cursor position
  1921                              <1> 	;
  1922 000013D3 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1923 000013D5 7647                <1> 	jbe	short u8
  1924                              <1> 	;
  1925                              <1> 	; write the char to the screen
  1926                              <1> u0:	
  1927                              <1> 	; ah = attribute/color
  1928                              <1> 	; al = character
  1929                              <1> 	; bl = video page number (0 to 7)
  1930                              <1> 	; bh = 0
  1931                              <1> 	;
  1932 000013D7 E8D2010000          <1> 	call	write_c_current
  1933                              <1> 	;
  1934                              <1> 	; position the cursor for next char
  1935 000013DC FEC2                <1> 	inc	dl		; next column
  1936                              <1> 	;cmp	dl, [CRT_COLS]
  1937 000013DE 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1938                              <1>         ;jne	set_cpos
  1939                              <1> 	; 02/02/2022
  1940 000013E1 7405                <1> 	je	short u13
  1941 000013E3 E9DE000000          <1> 	jmp	set_cpos
  1942                              <1> u13:
  1943 000013E8 B200                <1> 	mov	dl, 0		; column = 0
  1944                              <1> u10:				; (line feed found)
  1945 000013EA 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1946 000013ED 7228                <1> 	jb 	short u6
  1947                              <1> 	;
  1948                              <1> 	; scroll required
  1949                              <1> u1:	
  1950                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1951 000013EF E8D2000000          <1> 	call	set_cpos
  1952                              <1> 	;
  1953                              <1> 	; determine value to fill with during scroll
  1954                              <1> u2:
  1955                              <1> 	; READ_AC_CURRENT		:
  1956                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1957                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1958                              <1> 	;
  1959                              <1> 	; INPUT				
  1960                              <1> 	;	(AH) = CURRENT CRT MODE
  1961                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1962                              <1> 	;	(DS) = DATA SEGMENT
  1963                              <1> 	;	(ES) = REGEN SEGMENT
  1964                              <1> 	; OUTPUT			
  1965                              <1> 	;	(AL) = CHARACTER READ
  1966                              <1> 	;	(AH) = ATTRIBUTE READ
  1967                              <1> 	;
  1968                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1969                              <1> 	;
  1970                              <1> 	; bl = video page number
  1971                              <1> 	;
  1972 000013F4 E829010000          <1> 	call	find_position	; get regen location and port address
  1973                              <1> 	; dx = status port
  1974                              <1> 	; esi = cursor location/address
  1975                              <1> p11:
  1976 000013F9 FB                  <1> 	sti			; enable interrupts
  1977 000013FA 90                  <1> 	nop			; allow for small interupts window
  1978 000013FB FA                  <1> 	cli			; blocks interrupts for single loop
  1979 000013FC EC                  <1> 	in	al, dx		; get status from adapter
  1980 000013FD A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1981 000013FF 75F8                <1> 	jnz	short p11	; wait until it is
  1982                              <1> p12:				; now wait for either retrace high
  1983 00001401 EC                  <1> 	in	al, dx		; get status
  1984 00001402 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1985 00001404 74FB                <1> 	jz	short p12	; wait until either is active	
  1986                              <1> p13:
  1987 00001406 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1988 0000140C 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1989                              <1> 	;
  1990                              <1> 	; al = character, ah = attribute
  1991                              <1> 	;
  1992 0000140F FB                  <1> 	sti
  1993                              <1> 	; bl = video page number 	
  1994                              <1> u3:
  1995                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1996                              <1> 	;;sub	cx, cx		; upper left corner
  1997                              <1> 	;;mov	dh, 25-1 	; lower right row
  1998                              <1> 	;;;mov	dl, [CRT_COLS]
  1999                              <1> 	;mov	dl, 80		; lower right column	
  2000                              <1> 	;;dec	dl
  2001                              <1> 	;;mov	dl, 79
  2002                              <1> 
  2003                              <1> 	;;call	scroll_up	; 04/12/2013
  2004                              <1> 	;;; 11/03/2015
  2005                              <1> 	; 02/09/2014
  2006                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2007                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2008                              <1> 	; 11/03/2015
  2009                              <1> 	;sub	cx, cx
  2010                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2011                              <1> 	;
  2012                              <1> 	; 02/02/2022 (simplied scroll up)
  2013                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2014                              <1> 	;
  2015 00001410 B001                <1> 	mov	al, 1		; scroll 1 line up
  2016                              <1> 		; ah = attribute
  2017 00001412 E935010000          <1> 	jmp	scroll_up
  2018                              <1> ;u4:
  2019                              <1> 	;;int	10h		; video-call return
  2020                              <1> 				; scroll up the screen
  2021                              <1> 				; tty return
  2022                              <1> ;u5:
  2023                              <1> 	;retn			; return to the caller
  2024                              <1> 
  2025                              <1> u6:				; set-cursor-inc
  2026 00001417 FEC6                <1> 	inc	dh		; next row
  2027                              <1> 				; set cursor
  2028                              <1> ;u7:					
  2029                              <1> 	;;mov	ah, 02h
  2030                              <1> 	;;jmp	short u4 	; establish the new cursor
  2031                              <1> 	;call	set_cpos
  2032                              <1> 	;jmp 	short u5
  2033 00001419 E9A8000000          <1> 	jmp     set_cpos
  2034                              <1> 
  2035                              <1> 	; check for control characters
  2036                              <1> u8:
  2037 0000141E 7434                <1> 	je	short u9
  2038 00001420 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2039 00001422 74C6                <1> 	je	short u10
  2040 00001424 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2041 00001426 7430                <1> 	je	short u11
  2042 00001428 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2043                              <1> 	;jne	short u0
  2044 0000142A 7420                <1> 	je	short bs	; 12/12/2013
  2045                              <1> 	; 12/12/2013 (tab stop)
  2046 0000142C 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2047 0000142E 75A7                <1> 	jne	short u0
  2048 00001430 88D0                <1> 	mov	al, dl
  2049 00001432 6698                <1> 	cbw
  2050 00001434 B108                <1> 	mov	cl, 8
  2051 00001436 F6F1                <1> 	div	cl
  2052 00001438 28E1                <1> 	sub	cl, ah
  2053                              <1> ts:
  2054                              <1> 	; 02/09/2014
  2055                              <1> 	; 01/09/2014
  2056 0000143A B020                <1> 	mov	al, 20h
  2057                              <1> tsloop:
  2058                              <1> 	;push	cx
  2059                              <1> 	;push	ax
  2060                              <1> 	; 02/02/2022
  2061 0000143C 51                  <1> 	push	ecx
  2062 0000143D 50                  <1> 	push	eax
  2063 0000143E 30FF                <1> 	xor 	bh, bh
  2064                              <1> 	;mov	bl, [active_page]
  2065 00001440 E881FFFFFF          <1> 	call	m3
  2066                              <1> 	; 02/02/2022
  2067 00001445 58                  <1> 	pop	eax
  2068 00001446 59                  <1>  	pop	ecx
  2069                              <1> 	;pop	ax  ; ah = attribute/color
  2070                              <1> 	;pop	cx
  2071 00001447 FEC9                <1> 	dec	cl
  2072 00001449 75F1                <1> 	jnz	short tsloop
  2073 0000144B C3                  <1> 	retn
  2074                              <1> bs:	
  2075                              <1> 	; back space found
  2076 0000144C 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2077                              <1> 	;je	short u7 	; set_cursor
  2078 0000144E 7476                <1> 	jz	short set_cpos
  2079                              <1> 	;dec	dx     		; no -- just move it back
  2080                              <1> 	; 02/02/2022
  2081 00001450 FECA                <1> 	dec	dl
  2082                              <1> 	;jmp	short u7
  2083 00001452 EB72                <1> 	jmp	short set_cpos
  2084                              <1> 
  2085                              <1> 	; carriage return found
  2086                              <1> u9:
  2087 00001454 B200                <1> 	mov	dl, 0 		; move to first column
  2088                              <1> 	;jmp	short u7
  2089 00001456 EB6E                <1> 	jmp	short set_cpos
  2090                              <1> 
  2091                              <1> 	; line feed found
  2092                              <1> ;u10:
  2093                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2094                              <1> ;	jne	short u6 	; no, just set the cursor
  2095                              <1> ;       jmp     u1              ; yes, scroll the screen
  2096                              <1> 
  2097                              <1> beeper: 
  2098                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2099                              <1> 	; 18/01/2014
  2100                              <1> 	; 03/12/2013
  2101                              <1> 	; bell found
  2102                              <1> u11:
  2103 00001458 FB                  <1> 	sti
  2104 00001459 3A1D[36630000]      <1> 	cmp	bl, [active_page]
  2105 0000145F 7551                <1> 	jne	short u12	; Do not sound the beep 
  2106                              <1> 				; if it is not written on the active page
  2107 00001461 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2108 00001465 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2109                              <1> 	;call	beep		; sound the pod bell
  2110                              <1> 	;jmp	short u5 	; tty_return
  2111                              <1> 	;retn
  2112                              <1> 	
  2113                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2114                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2115                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2116                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2117                              <1> 
  2118                              <1> beep:
  2119                              <1> 	; 07/02/2015
  2120                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2121                              <1> 	; 18/01/2014
  2122                              <1> 	; 03/12/2013
  2123                              <1> 	;
  2124                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2125                              <1> 	;
  2126                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2127                              <1> 	;
  2128                              <1> 	; ENTRY:
  2129                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2130                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2131                              <1> 	; EXIT:			:
  2132                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2133                              <1> 
  2134 00001467 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2135 00001468 FA                  <1> 	cli			; block interrupts during update
  2136 00001469 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2137 0000146B E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2138 0000146D EB00                <1> 	jmp	$+2		; I/O delay
  2139 0000146F 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2140 00001471 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2141 00001473 EB00                <1> 	jmp	$+2		; I/O delay
  2142 00001475 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2143 00001477 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2144 00001479 E461                <1> 	in	al, PORT_B	; get current setting of port
  2145 0000147B 88C4                <1> 	mov	ah, al		; save that setting
  2146 0000147D 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2147 0000147F E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2148                              <1> 	;popf	; 18/01/2014
  2149 00001481 FB                  <1> 	sti
  2150                              <1> g7:				; 1/64 second per count (bl)
  2151 00001482 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2152 00001487 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2153 0000148C FECB                <1> 	dec	bl		; (bl) length count expired?
  2154 0000148E 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2155                              <1> 	;
  2156                              <1> 	;pushf			; save interrupt status
  2157 00001490 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2158 00001491 E461                <1> 	in	al, PORT_B	; get current port value
  2159                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2160 00001493 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2161 00001495 20C4                <1>         and	ah, al		; someone turned them off during beep
  2162 00001497 88E0                <1> 	mov	al, ah		; recover value of port
  2163                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2164 00001499 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2165 0000149B E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2166                              <1> 	;popf			; restore interrupt flag state
  2167 0000149D FB                  <1> 	sti
  2168 0000149E B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2169 000014A3 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2170                              <1> 	;pushf			; save interrupt status
  2171 000014A8 FA                  <1> 	cli			; block interrupts during update
  2172 000014A9 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2173 000014AB 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2174 000014AD 08E0                <1> 	or	al, ah		; recover value of port_b
  2175 000014AF E661                <1> 	out	PORT_B, al	; restore speaker status
  2176 000014B1 9D                  <1> 	popf			; restore interrupt flag state
  2177                              <1> u12:	
  2178 000014B2 C3                  <1> 	retn
  2179                              <1> 
  2180                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2181                              <1> 
  2182                              <1> WAITF:
  2183                              <1> waitf:
  2184                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2185                              <1> 	; 03/12/2013
  2186                              <1> 	;
  2187                              <1> ;	push	ax		; save work register (ah)	
  2188                              <1> ;waitf1:
  2189                              <1> 				; use timer 1 output bits
  2190                              <1> ;	in	al, PORT_B	; read current counter output status
  2191                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2192                              <1> ;	cmp	al, ah		; did it just change
  2193                              <1> ;	je	short waitf1	; wait for a change in output line
  2194                              <1> ;	;
  2195                              <1> ;	mov	ah, al		; save new lflag state
  2196                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2197                              <1> ;	;
  2198                              <1> ;	pop	ax		; restore (ah)
  2199                              <1> ;	retn			; return (cx)=0
  2200                              <1> 
  2201                              <1> ; 02/02/2022
  2202                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2203                              <1> ; 17/12/2014 (dsectrm2.s)
  2204                              <1> ; WAITF
  2205                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2206                              <1> ;
  2207                              <1> ;---WAITF-----------------------------------------------------------------------
  2208                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2209                              <1> ; ENTRY:
  2210                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2211                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2212                              <1> ; EXIT:
  2213                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2214                              <1> ;	(CX) = 0	
  2215                              <1> ;-------------------------------------------------------------------------------
  2216                              <1> 
  2217                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2218                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2219                              <1> 
  2220                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2221 000014B3 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2222                              <1> 	;push	ax
  2223                              <1> 	; 16/12/2014
  2224                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2225 000014B4 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2226                              <1> ;17/12/2014	
  2227                              <1> ;WAITF1:
  2228                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2229                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2230                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2231                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2232                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2233                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2234                              <1> 	;
  2235                              <1> 	; 17/12/2014
  2236                              <1> 	;
  2237                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2238                              <1> 	;
  2239                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2240                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2241                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2242                              <1> WR_STATE_0:
  2243 000014B6 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2244 000014B8 A810                <1> 	TEST	AL,010H
  2245 000014BA 74FA                <1> 	JZ	SHORT WR_STATE_0
  2246                              <1> WR_STATE_1:
  2247 000014BC E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2248 000014BE A810                <1> 	TEST	AL,010H
  2249 000014C0 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2250 000014C2 E2F2                <1>         LOOP    WR_STATE_0
  2251                              <1> 	;
  2252                              <1> 	;pop	ax
  2253 000014C4 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2254 000014C5 C3                  <1> 	RETn				; (CX) = 0
  2255                              <1> 
  2256                              <1> set_cpos:
  2257                              <1> 	; 14/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  2258                              <1> 	; 25/02/2022
  2259                              <1> 	; 23/02/2022
  2260                              <1> 	; 02/02/2022
  2261                              <1> 	; 27/06/2015
  2262                              <1> 	; 01/09/2014
  2263                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2264                              <1> 	;
  2265                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2266                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2267                              <1> 	;
  2268                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2269                              <1> 	;
  2270                              <1> 	; SET_CPOS
  2271                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2272                              <1> 	;	NEW X-Y VALUES PASSED
  2273                              <1> 	; INPUT
  2274                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2275                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2276                              <1> 	; OUTPUT
  2277                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2278                              <1> 	;
  2279 000014C6 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2280 000014C9 D0E0                <1>         shl     al, 1   ; word offset
  2281 000014CB BE[26630000]        <1> 	mov	esi, cursor_posn
  2282 000014D0 01C6                <1>         add     esi, eax
  2283 000014D2 668916              <1> 	mov	[esi], dx ; save the pointer
  2284 000014D5 381D[36630000]      <1> 	cmp	[active_page], bl
  2285 000014DB 7531                <1> 	jne	short m17
  2286                              <1> 
  2287                              <1> 	; 14/06/2022	
  2288                              <1> 	;cli ; 25/02/2022
  2289                              <1> 
  2290                              <1> 	;call	m18	;h CURSOR SET
  2291                              <1> ;m17:			; SET_CPOS_RETURN
  2292                              <1> 	; 01/09/2014
  2293                              <1> 	;retn
  2294                              <1> 		; DX = row/column
  2295                              <1> m18:
  2296 000014DD E832000000          <1> 	call	position ; determine location in regen buffer	
  2297                              <1> 	;mov	cx, [CRT_START]
  2298                              <1> 	; 23/02/2022
  2299 000014E2 0FB70D[24630000]    <1> 	movzx	ecx, word [CRT_START]
  2300 000014E9 01C1                <1> 	add	ecx, eax
  2301                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2302                              <1> 			; to the start address (offset) for this page
  2303                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2304                              <1> 	; 23/02/2022
  2305 000014EB D1E9                <1> 	shr	ecx, 1
  2306 000014ED B40E                <1> 	mov	ah, 14	; register number for cursor
  2307                              <1> 	
  2308                              <1> 	; 14/06/2022
  2309                              <1> 	;call	m16	; output value to the 6845
  2310                              <1> 	;sti	; 25/02/2022
  2311                              <1> 	;retn
  2312                              <1> 
  2313                              <1> 	; 14/06/2022
  2314                              <1> 	; 25/02/2022
  2315                              <1> 	; 02/02/2022
  2316                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2317                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2318                              <1> m16:
  2319                              <1> 	; 14/06/2022
  2320 000014EF FA                  <1> 	cli	; 25/02/2022
  2321                              <1> 	;mov	dx, [addr_6845] ; address register
  2322 000014F0 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2323 000014F4 88E0                <1> 	mov	al, ah	; get value
  2324 000014F6 EE                  <1> 	out	dx, al	; register set
  2325                              <1> 	;inc	dx	; data register
  2326                              <1> 	; 02/02/2022
  2327 000014F7 FEC2                <1> 	inc	dl
  2328 000014F9 EB00                <1> 	jmp	$+2	; i/o delay
  2329 000014FB 88E8                <1> 	mov	al, ch	; data
  2330 000014FD EE                  <1> 	out	dx, al	
  2331                              <1> 	;dec	dx
  2332                              <1> 	; 02/02/2022	
  2333 000014FE FECA                <1> 	dec	dl
  2334 00001500 88E0                <1> 	mov	al, ah
  2335 00001502 FEC0                <1> 	inc	al	; point to other data register
  2336 00001504 EE                  <1> 	out	dx, al	; set for second register
  2337                              <1> 	;inc	dx
  2338                              <1> 	; 02/02/2022
  2339 00001505 FEC2                <1> 	inc	dl
  2340 00001507 EB00                <1> 	jmp	$+2	; i/o delay
  2341 00001509 88C8                <1> 	mov	al, cl	; second data value
  2342 0000150B EE                  <1> 	out	dx, al
  2343                              <1> 	; 14/06/2022
  2344 0000150C FB                  <1> 	sti	; 25/02/2022
  2345                              <1> ;m17:
  2346 0000150D C3                  <1> 	retn
  2347                              <1> m17:
  2348                              <1> 	; 14/06/2022
  2349                              <1> 	; ('write_tty' must not return to 'putc' with cf)
  2350 0000150E F8                  <1> 	clc
  2351 0000150F C3                  <1> 	retn
  2352                              <1> 
  2353                              <1> set_ctype:
  2354                              <1> 	; 07/02/2022
  2355                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2356                              <1> 	;
  2357                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2358                              <1> 
  2359                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2360                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2361                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2362                              <1> ;          OR NO CURSOR AT ALL
  2363                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2364                              <1> 
  2365                              <1> ;------------------------------------------------
  2366                              <1> ; SET_CTYPE
  2367                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2368                              <1> ; INPUT
  2369                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2370                              <1> ; OUTPUT	
  2371                              <1> ;	NONE
  2372                              <1> ;------------------------------------------------
  2373                              <1> 
  2374 00001510 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2375                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2376                              <1> 	;call	m16	; output cx register
  2377                              <1> 	;retn
  2378                              <1> 	; 07/02/2022
  2379 00001512 EBDB                <1> 	jmp	short m16
  2380                              <1> 
  2381                              <1> position:
  2382                              <1> 	; 23/02/2022
  2383                              <1> 	; 02/02/2022
  2384                              <1> 	; 27/06/2015
  2385                              <1> 	; 02/09/2014
  2386                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2387                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2388                              <1> 	;
  2389                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2390                              <1> 	;
  2391                              <1> 	; POSITION
  2392                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2393                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2394                              <1> 	; INPUT
  2395                              <1> 	;	AX = ROW, COLUMN POSITION
  2396                              <1> 	; OUTPUT
  2397                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2398                              <1> 
  2399                              <1> 		; DX = ROW, COLUMN POSITION
  2400                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2401 00001514 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2402 00001516 B050                <1> 	mov	al, 80	; determine bytes to row	
  2403 00001518 F6E6                <1> 	mul	dh	; row value
  2404                              <1> 	;xor	dh, dh	; 0
  2405                              <1> 	;add	ax, dx	; add column value to the result
  2406                              <1> 	; 23/02/2022
  2407 0000151A 00D0                <1> 	add	al, dl
  2408 0000151C 80D400              <1> 	adc	ah, 0	
  2409                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2410                              <1> 	; 02/02/2022
  2411 0000151F D1E0                <1> 	shl	eax, 1
  2412                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2413 00001521 C3                  <1> 	retn
  2414                              <1> 
  2415                              <1> find_position:
  2416                              <1> 	; 02/02/2022
  2417                              <1> 	; 27/06/2015
  2418                              <1> 	; 07/09/2014
  2419                              <1> 	; 02/09/2014
  2420                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2421                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2422 00001522 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2423 00001525 89CE                <1> 	mov	esi, ecx
  2424                              <1> 	;shl	si, 1
  2425                              <1> 	; 02/02/2022
  2426 00001527 D1E6                <1> 	shl	esi, 1
  2427 00001529 668B96[26630000]    <1> 	mov	dx, [esi+cursor_posn]
  2428 00001530 7409                <1> 	jz	short p21
  2429                              <1> 	;xor	si, si
  2430                              <1> 	; 02/02/2022
  2431 00001532 31F6                <1> 	xor	esi, esi
  2432                              <1> p20:
  2433                              <1> 	;add	si, [CRT_LEN]
  2434 00001534 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2435 00001539 E2F9                <1> 	loop	p20
  2436                              <1> p21:
  2437 0000153B 6621D2              <1> 	and	dx, dx
  2438 0000153E 7407                <1> 	jz	short p22
  2439 00001540 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2440 00001545 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2441                              <1> p22:	
  2442                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2443                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2444                              <1> 	;add	dx, 6	; point at status port
  2445 00001547 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2446                              <1> 	; cx = 0
  2447 0000154B C3                  <1> 	retn
  2448                              <1> 
  2449                              <1> scroll_up:
  2450                              <1> 	; 02/02/2022 (simplified scroll up)
  2451                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2452                              <1> 	; 16/01/2016
  2453                              <1> 	; 07/09/2014
  2454                              <1> 	; 02/09/2014
  2455                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2456                              <1> 	; 04/04/2014
  2457                              <1> 	; 04/12/2013
  2458                              <1> 	;
  2459                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2460                              <1> 	;
  2461                              <1> 	; SCROLL UP
  2462                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2463                              <1> 	;	ON THE SCREEN
  2464                              <1> 	; INPUT
  2465                              <1> 	;	(AH) = CURRENT CRT MODE
  2466                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2467                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2468                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2469                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2470                              <1> 	;	(DS) = DATA SEGMENT
  2471                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2472                              <1> 	; OUTPUT
  2473                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2474                              <1> 	;
  2475                              <1> 	;	bh = 0  (02/09/2014)
  2476                              <1> 	;
  2477                              <1> 	; ((ah = 3))
  2478                              <1> 	; cl = left upper column
  2479                              <1> 	; ch = left upper row
  2480                              <1> 	; dl = right lower column
  2481                              <1> 	; dh = right lower row
  2482                              <1> 	;
  2483                              <1> 	; al = line count 
  2484                              <1> 	; ah = attribute to be used on blanked line
  2485                              <1> 	; bl = video page number (0 to 7)
  2486                              <1> 	; 
  2487                              <1> 
  2488                              <1> 	; 02/02/2022 'scroll_up' code
  2489                              <1> 	; ------------------------------------------------------
  2490                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2491                              <1> 
  2492                              <1> 	; INPUT:
  2493                              <1> 	;		
  2494                              <1> 	; al = line count 
  2495                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2496                              <1> 	; ah = attribute to be used on blanked line
  2497                              <1> 	; bl = video page number (0 to 7)
  2498                              <1> 
  2499                              <1> 	;cli
  2500 0000154C 31C9                <1> 	xor	ecx, ecx
  2501 0000154E 88C1                <1> 	mov	cl, al ; line count (cl)
  2502 00001550 BE00800B00          <1> 	mov	esi, 0B8000h
  2503 00001555 3A1D[36630000]      <1> 	cmp	bl, [active_page]
  2504 0000155B 7411                <1> 	je	short n1
  2505 0000155D 20DB                <1> 	and	bl, bl
  2506 0000155F 7422                <1> 	jz	short n3
  2507 00001561 88DD                <1> 	mov	ch, bl ; video page number
  2508                              <1> n0:
  2509 00001563 6681C6A00F          <1> 	add	si, 25*80*2
  2510 00001568 FECD                <1> 	dec	ch
  2511 0000156A 75F7                <1> 	jnz	short n0
  2512 0000156C EB15                <1> 	jmp	short n3
  2513                              <1> n1:
  2514 0000156E 660335[24630000]    <1> 	add	si, [CRT_START]
  2515                              <1> 	;
  2516 00001575 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2517                              <1> n2:			 ; wait_display_enable
  2518 00001579 EC                  <1> 	in	al, dx	 ; get port
  2519 0000157A A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2520 0000157C 74FB                <1> 	jz	short n2 ; wait_display_enable
  2521 0000157E B025                <1> 	mov	al, 25h
  2522 00001580 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2523 00001582 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2524                              <1> n3:
  2525                              <1> 	; cl = line count
  2526                              <1> 	; ah = attribute/color
  2527 00001583 89F7                <1> 	mov	edi, esi
  2528 00001585 20C9                <1> 	and	cl, cl
  2529 00001587 741F                <1> 	jz	short n6
  2530 00001589 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2531 0000158E 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2532 00001592 F366A5              <1> 	rep	movsw
  2533 00001595 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2534                              <1> n4:
  2535                              <1> 	; ah = character attribute/cocor
  2536 00001597 B020                <1> 	mov	al, 20h ; fill with blanks
  2537 00001599 F366AB              <1> 	rep	stosw
  2538                              <1> 
  2539 0000159C 3A1D[36630000]      <1> 	cmp	bl, [active_page]
  2540 000015A2 7503                <1> 	jne	short n5
  2541                              <1> 
  2542                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2543 000015A4 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2544                              <1> 	;mov	dx, 03D8h ; always set color card port
  2545 000015A6 EE                  <1> 	out	dx, al
  2546                              <1> n5:
  2547 000015A7 C3                  <1> 	retn
  2548                              <1> n6:
  2549                              <1> 	; clear video page
  2550 000015A8 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2551 000015AC EBE9                <1> 	jmp	short n4
  2552                              <1> 
  2553                              <1> 	; 23/02/2022
  2554                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2555                              <1> 	; ------------------------------------------------------
  2556                              <1> 
  2557                              <1> 	; Test	Line Count
  2558                              <1> 	or	al, al
  2559                              <1> 	jz	short al_set
  2560                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2561                              <1> 	sub	bh, ch
  2562                              <1> 	inc	bh	; adjust difference by 1
  2563                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2564                              <1> 	jne	short al_set ; if not the we're all set
  2565                              <1> 	xor	al, al	; otherwise set al to zero
  2566                              <1> al_set:
  2567                              <1> 	xor	bh, bh	; 0
  2568                              <1> 	;push	ax
  2569                              <1> 	push	eax ; 23/02/2022
  2570                              <1> 	;mov 	esi, [crt_base]
  2571                              <1>         mov     esi, 0B8000h  
  2572                              <1>         cmp     bl, [active_page]
  2573                              <1> 	jne	short n0
  2574                              <1> 	;
  2575                              <1>         mov     ax, [CRT_START]
  2576                              <1>         add     si, ax
  2577                              <1>         jmp     short n1
  2578                              <1> n0:
  2579                              <1>         and     bl, bl
  2580                              <1> 	jz	short n1
  2581                              <1> 	mov	al, bl
  2582                              <1> n0x:
  2583                              <1>         ;add    si, [CRT_LEN]
  2584                              <1>         ;add    esi, 80*25*2 
  2585                              <1>         add     si, 80*25*2
  2586                              <1>         dec	al
  2587                              <1> 	jnz	short n0x
  2588                              <1> n1:	
  2589                              <1>         ; Scroll position
  2590                              <1> 	;push	dx ; 23/02/2022
  2591                              <1> 	mov	dx, cx	; now, upper left position in DX
  2592                              <1> 	call	position
  2593                              <1> 	add	esi, eax
  2594                              <1> 	mov	edi, esi
  2595                              <1> 	;pop	dx	; lower right position in DX
  2596                              <1> 	sub	dx, cx
  2597                              <1> 	inc	dh	; dh = #rows 
  2598                              <1> 	inc	dl	; dl = #cols in block
  2599                              <1> 	;pop	ax	; al = line count, ah = attribute
  2600                              <1> 	pop	eax ; 23/02/2022
  2601                              <1> 	xor	ecx, ecx
  2602                              <1> 	mov	cx, ax
  2603                              <1> 	;mov	ah, [CRT_COLS]
  2604                              <1> 	mov	ah, 80
  2605                              <1> 	mul	ah	; determine offset to from address
  2606                              <1> 	add	ax, ax  ; *2 for attribute byte
  2607                              <1> 	;
  2608                              <1> 	;push	ax	; offset 
  2609                              <1> 	;push	dx
  2610                              <1> 	; 23/02/2022
  2611                              <1> 	push	eax
  2612                              <1> 	push	edx
  2613                              <1> 	;
  2614                              <1> 	; 04/04/2014
  2615                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2616                              <1> n8:                      ; wait_display_enable
  2617                              <1>         in      al, dx   ; get port
  2618                              <1> 	test	al, RVRT ; wait for vertical retrace
  2619                              <1> 	jz	short n8 ; wait_display_enable
  2620                              <1> 	mov	al, 25h
  2621                              <1> 	mov	dl, 0D8h ; address control port
  2622                              <1> 	out	dx, al	; turn off video during vertical retrace
  2623                              <1> 	;pop	dx	; #rows, #cols
  2624                              <1>        	;pop	ax	; offset
  2625                              <1> 	; 23/02/2022
  2626                              <1> 	pop	edx
  2627                              <1> 	pop	eax
  2628                              <1> 	xchg	ax, cx	; 
  2629                              <1> 	; ecx = offset, al = line count, ah = attribute
  2630                              <1> ;n9:
  2631                              <1> 	or	al, al
  2632                              <1>         jz      short n3 
  2633                              <1>         add     esi, ecx ; from address for scroll
  2634                              <1> 	mov	bh, dh  ; #rows in block
  2635                              <1> 	sub	bh, al	; #rows to be moved
  2636                              <1> n2:
  2637                              <1> 	; Move rows
  2638                              <1> 	mov	cl, dl	; get # of cols to move
  2639                              <1> 	push	esi
  2640                              <1> 	push	edi	; save start address
  2641                              <1> n10:
  2642                              <1> 	movsw		; move that line on screen
  2643                              <1> 	dec	cl
  2644                              <1>         jnz     short n10
  2645                              <1> 	pop	edi
  2646                              <1> 	pop	esi	; recover addresses
  2647                              <1>         ;mov    cl, [CRT_COLS] 
  2648                              <1> 	;add	cl, cl
  2649                              <1>         ;mov    ecx, 80*2
  2650                              <1>         mov     cx, 80*2
  2651                              <1>         add     esi, ecx  ; next line
  2652                              <1>         add     edi, ecx
  2653                              <1> 	dec	bh	 ; count of lines to move
  2654                              <1> 	jnz	short n2 ; row loop
  2655                              <1> 	; bh = 0
  2656                              <1> 	mov	dh, al	 ; #rows	
  2657                              <1> n3:
  2658                              <1> 	; attribute in ah
  2659                              <1> 	mov	al, ' '	 ; fill with blanks
  2660                              <1> n3x:
  2661                              <1> 	; Clear rows
  2662                              <1>                 ; dh =  #rows
  2663                              <1>         mov	cl, dl	; get # of cols to clear
  2664                              <1>         push    edi     ; save address
  2665                              <1> n11:
  2666                              <1>         stosw           ; store fill character
  2667                              <1> 	dec	cl
  2668                              <1>         jnz     short n11
  2669                              <1>         pop     edi     ; recover address
  2670                              <1> 	;mov	cl, [CRT_COLS]
  2671                              <1> 	;add	cl, cl
  2672                              <1>         ;mov    ecx, 80*2
  2673                              <1>         mov	cl, 80*2
  2674                              <1>         add     edi, ecx
  2675                              <1> 	dec	dh
  2676                              <1> 	jnz	short n3x ; 16/01/2016
  2677                              <1> 	;
  2678                              <1> 	cmp	bl, [active_page]
  2679                              <1> 	jne	short n6
  2680                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2681                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2682                              <1> 	mov	dx, 03D8h ; always set color card port
  2683                              <1> 	out	dx, al
  2684                              <1> n6:
  2685                              <1> 	retn
  2686                              <1> 
  2687                              <1> %endif
  2688                              <1> 
  2689                              <1> write_c_current:
  2690                              <1> 	; 02/02/2022
  2691                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2692                              <1> 	; 18/01/2014
  2693                              <1> 	; 04/12/2013
  2694                              <1> 	;
  2695                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2696                              <1> 	;
  2697                              <1> 	; WRITE_C_CURRENT
  2698                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2699                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2700                              <1> 	; INPUT	
  2701                              <1> 	;	(AH) = CURRENT CRT MODE
  2702                              <1> 	;	(BH) = DISPLAY PAGE
  2703                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2704                              <1> 	;	(AL) = CHAR TO WRITE
  2705                              <1> 	;	(DS) = DATA SEGMENT
  2706                              <1> 	;	(ES) = REGEN SEGMENT
  2707                              <1> 	; OUTPUT
  2708                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2709                              <1> 
  2710 000015AE FA                  <1> 	cli		
  2711                              <1> 	; bl = video page
  2712                              <1> 	; al = character
  2713                              <1> 	; ah = color/attribute
  2714                              <1> 	;push	dx
  2715                              <1> 	;push	ax	; save character & attribute/color
  2716                              <1> 	; 02/02/2022
  2717 000015AF 52                  <1> 	push	edx
  2718 000015B0 50                  <1> 	push	eax
  2719 000015B1 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2720                              <1> 	; esi = regen location
  2721                              <1> 	; dx = status port
  2722                              <1> 	;
  2723                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2724                              <1> 	;
  2725                              <1> p41:			; wait for horizontal retrace is low or vertical
  2726 000015B6 FB                  <1> 	sti		; enable interrupts first
  2727 000015B7 3A1D[36630000]      <1>         cmp     bl, [active_page]
  2728 000015BD 7510                <1> 	jne	short p44 
  2729 000015BF FA                  <1> 	cli 		; block interrupts for single loop
  2730 000015C0 EC                  <1> 	in	al, dx	; get status from the adapter
  2731 000015C1 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2732 000015C3 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2733 000015C5 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2734 000015C7 75ED                <1> 	jnz	short p41 ; wait until it is
  2735                              <1> p42:			; wait for either retrace high
  2736 000015C9 EC                  <1> 	in	al, dx	; get status again
  2737 000015CA A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2738 000015CC 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2739                              <1> p43:	
  2740 000015CE FB                  <1> 	sti
  2741                              <1> p44:
  2742                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2743                              <1> 	; 02/02/2022
  2744 000015CF 58                  <1> 	pop	eax
  2745 000015D0 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2746                              <1> 			; Retro UNIX 386 v1 feature only!
  2747 000015D6 668906              <1> 	mov	[esi], ax
  2748                              <1> 	;pop	dx
  2749                              <1> 	; 02/02/2022
  2750 000015D9 5A                  <1> 	pop	edx
  2751 000015DA C3                  <1> 	retn
  2752                              <1> 
  2753                              <1> %if 0	; 02/02/2022
  2754                              <1> 
  2755                              <1> set_mode:
  2756                              <1> 	; 02/02/2022
  2757                              <1> 	; 16/01/2016
  2758                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2759                              <1> 	;
  2760                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2761                              <1> 
  2762                              <1> ;------------------------------------------------------
  2763                              <1> ; SET MODE					      :
  2764                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2765                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2766                              <1> ; INPUT						      :
  2767                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2768                              <1> ; OUTPUT					      :
  2769                              <1> ;	NONE					      :
  2770                              <1> ;------------------------------------------------------
  2771                              <1> 
  2772                              <1> 	push	edi ; 16/01/2016
  2773                              <1> 	push	ebx
  2774                              <1> 	push	edx
  2775                              <1> 	push	ecx ; 16/01/2016
  2776                              <1>         push    eax
  2777                              <1> 
  2778                              <1> 	;mov	dx, 03D4h 	; address or color card
  2779                              <1> 	mov	al, 3
  2780                              <1> ;M8:
  2781                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2782                              <1> 	mov	al, 29h
  2783                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2784                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2785                              <1> 	;push	dx  		; save port value
  2786                              <1> 	;add	dx, 4		; point to control register
  2787                              <1> 	mov	dx, 3D8h
  2788                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2789                              <1> 	;pop	dx
  2790                              <1> ;M9:
  2791                              <1> 	mov	ebx, video_params ; initialization table
  2792                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2793                              <1> 	;xchg 	ah, al
  2794                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2795                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2796                              <1> 	
  2797                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2798                              <1> 	; 02/02/2022
  2799                              <1> 	; dx = 3D8h
  2800                              <1> 	xor	ecx, ecx
  2801                              <1> 	mov	cl, 16
  2802                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2803                              <1> M10:			;  initialization loop
  2804                              <1> 	mov	al, ah 	; get 6845 register number
  2805                              <1> 	out	dx, al
  2806                              <1> 	;inc	dx      ; point to data port
  2807                              <1> 	; 02/02/2022
  2808                              <1> 	inc	dl ; 3D9h
  2809                              <1> 	inc	ah	; next register value
  2810                              <1> 	mov	al, [ebx] ; get table value
  2811                              <1> 	out	dx, al	; out to chip
  2812                              <1> 	inc	ebx	; next in table
  2813                              <1> 	;dec	dx	; back to pointer register
  2814                              <1> 	; 02/02/2022
  2815                              <1> 	dec	dl ; 3D8h
  2816                              <1> 	loop	M10	; do the whole table
  2817                              <1> 	
  2818                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2819                              <1> 	;xor	ax, ax  
  2820                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2821                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2822                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2823                              <1> 	; black background, light gray characeter color, space character
  2824                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2825                              <1> ;M13:			  ; clear buffer
  2826                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2827                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2828                              <1> 
  2829                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2830                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2831                              <1> 			 ; prepare to output to video enable port
  2832                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2833                              <1> 	; 02/02/2022
  2834                              <1> 	;mov	dx, 3D8h
  2835                              <1> 	; 
  2836                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2837                              <1> 	mov	al, 29h
  2838                              <1> 	out	dx, al	 ; set video enable port
  2839                              <1> 
  2840                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2841                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2842                              <1> 	;
  2843                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2844                              <1> 	;
  2845                              <1> ;-----	SET CURSOR POSITIONS
  2846                              <1> 	;push	edi
  2847                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2848                              <1> 	mov	edi, cursor_posn
  2849                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2850                              <1> 	xor	eax, eax
  2851                              <1> 	rep 	stosd	; fill with zeroes
  2852                              <1> 	;pop	edi
  2853                              <1> 
  2854                              <1> ;-----	SET UP OVERSCAN REGISTER
  2855                              <1> 	inc	dx	; set overscan port to a default
  2856                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2857                              <1> ;M14:
  2858                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2859                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2860                              <1> 
  2861                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2862                              <1> 	;
  2863                              <1> 	pop	eax
  2864                              <1> 	pop	ecx ; 16/01/2016
  2865                              <1> 	pop	edx
  2866                              <1> 	pop	ebx
  2867                              <1> 	pop	edi ; 16/01/2016
  2868                              <1> 	retn
  2869                              <1> 
  2870                              <1> %endif
  2871                              <1> 	
  2872                              <1> tty_sw:
  2873                              <1> 	; 02/02/2022
  2874                              <1> 	; 30/06/2015
  2875                              <1> 	; 27/06/2015 
  2876                              <1> 	; 07/09/2014
  2877                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2878                              <1> 	;
  2879                              <1> 	; (Modified registers : EAX)
  2880                              <1> 	;
  2881                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2882                              <1> 	;
  2883                              <1> ;act_disp_page:
  2884                              <1> 	; 30/06/2015
  2885                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2886                              <1> 	; 10/12/2013
  2887                              <1> 	; 04/12/2013
  2888                              <1> 	;
  2889                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2890                              <1> 	;
  2891                              <1> 	; ACT_DISP_PAGE
  2892                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2893                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2894                              <1> 	; INPUT
  2895                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2896                              <1> 	; OUTPUT
  2897                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2898                              <1> 
  2899                              <1> 	;cli
  2900                              <1> 
  2901 000015DB 53                  <1> 	push	ebx
  2902                              <1> 	;push	cx
  2903                              <1> 	;push	dx
  2904                              <1> 	; 02/02/2022
  2905 000015DC 51                  <1> 	push	ecx
  2906 000015DD 52                  <1> 	push	edx
  2907                              <1> 	;
  2908 000015DE A2[36630000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2909                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2910                              <1> 	;mov	cx, 25*80*2
  2911                              <1> 	; 02/02/2022
  2912 000015E3 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2913                              <1> 	; 27/06/2015
  2914 000015E8 0FB6D8              <1> 	movzx	ebx, al
  2915                              <1> 	; 02/02/2022
  2916 000015EB 89D8                <1> 	mov	eax, ebx
  2917                              <1> 	;
  2918                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2919                              <1> 	;mul 	cx	; display page times regen length
  2920                              <1> 	; 02/02/2022
  2921 000015ED F7E1                <1> 	mul	ecx	
  2922                              <1> 	; 10/12/2013
  2923 000015EF 66A3[24630000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2924                              <1> 	;mov	cx, ax	; start address to cx
  2925                              <1> 	; 02/02/2022
  2926 000015F5 89C1                <1> 	mov	ecx, eax
  2927                              <1> 	;sar	cx, 1
  2928                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2929                              <1> 	; 02/02/2022
  2930 000015F7 D1E9                <1> 	shr	ecx, 1
  2931 000015F9 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2932 000015FB E8EFFEFFFF          <1> 	call	m16
  2933                              <1> 	;sal	bx, 1
  2934                              <1> 	; 01/09/2014
  2935 00001600 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2936 00001602 81C3[26630000]      <1> 	add	ebx, cursor_posn
  2937 00001608 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2938 0000160B E8CDFEFFFF          <1> 	call	m18
  2939                              <1> 	;
  2940                              <1> 	;pop	dx
  2941                              <1> 	;pop	cx
  2942                              <1> 	; 02/02/2022
  2943 00001610 5A                  <1> 	pop	edx
  2944 00001611 59                  <1> 	pop	ecx
  2945 00001612 5B                  <1> 	pop	ebx
  2946                              <1> 	;
  2947                              <1> 	;sti
  2948                              <1> 	;
  2949 00001613 C3                  <1> 	retn
  2950                              <1> 
  2951                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2952                              <1> 
  2953                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1833                                  
  1834                                  setup_rtc_int:
  1835                                  ; source: http://wiki.osdev.org/RTC
  1836 00001614 FA                      	cli		; disable interrupts
  1837                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1838                                  	; in order to change this ...
  1839                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1840                                  	; (rate must be above 2 and not over 15)
  1841                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1842 00001615 B08A                    	mov	al, 8Ah 
  1843 00001617 E670                    	out	70h, al ; set index to register A, disable NMI
  1844 00001619 90                      	nop
  1845 0000161A E471                    	in	al, 71h ; get initial value of register A
  1846 0000161C 88C4                    	mov 	ah, al
  1847 0000161E 80E4F0                  	and	ah, 0F0h
  1848 00001621 B08A                    	mov	al, 8Ah 
  1849 00001623 E670                    	out	70h, al ; reset index to register A
  1850 00001625 88E0                    	mov	al, ah
  1851 00001627 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1852 00001629 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1853                                  	; enable RTC interrupt
  1854 0000162B B08B                    	mov	al, 8Bh ;
  1855 0000162D E670                    	out	70h, al ; select register B and disable NMI
  1856 0000162F 90                      	nop
  1857 00001630 E471                    	in	al, 71h ; read the current value of register B
  1858 00001632 88C4                    	mov	ah, al  ;
  1859 00001634 B08B                    	mov 	al, 8Bh ;
  1860 00001636 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1861 00001638 88E0                    	mov	al, ah  ;
  1862 0000163A 0C40                    	or	al, 40h ;
  1863 0000163C E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1864 0000163E FB                      	sti
  1865 0000163F C3                      	retn
  1866                                  
  1867                                  ; Write memory information
  1868                                  ; Temporary Code
  1869                                  ; 06/11/2014
  1870                                  ; 14/08/2015 
  1871                                  memory_info:	
  1872 00001640 A1[0C630000]            	mov	eax, [memory_size] ; in pages
  1873 00001645 50                      	push	eax
  1874 00001646 C1E00C                  	shl	eax, 12		   ; in bytes
  1875 00001649 BB0A000000              	mov	ebx, 10
  1876 0000164E 89D9                    	mov	ecx, ebx	   ; 10
  1877 00001650 BE[735F0000]            	mov	esi, mem_total_b_str	
  1878 00001655 E8B2000000              	call	bintdstr
  1879 0000165A 58                      	pop	eax
  1880 0000165B B107                    	mov	cl, 7
  1881 0000165D BE[975F0000]            	mov	esi, mem_total_p_str
  1882 00001662 E8A5000000              	call	bintdstr	
  1883                                  	; 14/08/2015
  1884 00001667 E8BD000000              	call	calc_free_mem
  1885                                  	; edx = calculated free pages
  1886                                  	; ecx = 0
  1887 0000166C A1[10630000]            	mov 	eax, [free_pages]
  1888 00001671 39D0                    	cmp	eax, edx ; calculated free mem value 
  1889                                  		; and initial free mem value are same or not?
  1890 00001673 751D                    	jne 	short pmim ; print mem info with '?' if not
  1891 00001675 52                      	push 	edx ; free memory in pages	
  1892                                  	;mov 	eax, edx
  1893 00001676 C1E00C                  	shl	eax, 12 ; convert page count
  1894                                  			; to byte count
  1895 00001679 B10A                    	mov	cl, 10
  1896 0000167B BE[B75F0000]            	mov	esi, free_mem_b_str
  1897 00001680 E887000000              	call	bintdstr
  1898 00001685 58                      	pop	eax
  1899 00001686 B107                    	mov	cl, 7
  1900 00001688 BE[DB5F0000]            	mov	esi, free_mem_p_str
  1901 0000168D E87A000000              	call	bintdstr
  1902                                  pmim:
  1903 00001692 BE[615F0000]            	mov	esi, msg_memory_info
  1904                                  pmim_nb:	
  1905 00001697 AC                      	lodsb
  1906 00001698 08C0                    	or	al, al
  1907 0000169A 740D                    	jz	short pmim_ok
  1908 0000169C 56                      	push	esi
  1909 0000169D 31DB                    	xor	ebx, ebx ; 0
  1910                                  			; Video page 0 (bl=0)
  1911 0000169F B407                    	mov	ah, 07h ; Black background, 
  1912                                  			; light gray forecolor
  1913 000016A1 E816FDFFFF              	call	write_tty
  1914 000016A6 5E                      	pop	esi
  1915 000016A7 EBEE                    	jmp	short pmim_nb
  1916                                  pmim_ok:
  1917 000016A9 C3                      	retn
  1918                                  
  1919                                  ; Convert binary number to hexadecimal string
  1920                                  ; 10/05/2015  
  1921                                  ; dsectpm.s (28/02/2015)
  1922                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1923                                  ; 01/12/2014
  1924                                  ; 25/11/2014
  1925                                  ;
  1926                                  bytetohex:
  1927                                  	; INPUT ->
  1928                                  	; 	AL = byte (binary number)
  1929                                  	; OUTPUT ->
  1930                                  	;	AX = hexadecimal string
  1931                                  	;
  1932 000016AA 53                      	push	ebx
  1933 000016AB 31DB                    	xor	ebx, ebx
  1934 000016AD 88C3                    	mov	bl, al
  1935 000016AF C0EB04                  	shr	bl, 4
  1936 000016B2 8A9B[FC160000]          	mov	bl, [ebx+hexchrs] 	 	
  1937 000016B8 86D8                    	xchg	bl, al
  1938 000016BA 80E30F                  	and	bl, 0Fh
  1939 000016BD 8AA3[FC160000]          	mov	ah, [ebx+hexchrs] 
  1940 000016C3 5B                      	pop	ebx	
  1941 000016C4 C3                      	retn
  1942                                  
  1943                                  wordtohex:
  1944                                  	; INPUT ->
  1945                                  	; 	AX = word (binary number)
  1946                                  	; OUTPUT ->
  1947                                  	;	EAX = hexadecimal string
  1948                                  	;
  1949 000016C5 53                      	push	ebx
  1950 000016C6 31DB                    	xor	ebx, ebx
  1951 000016C8 86E0                    	xchg	ah, al
  1952 000016CA 6650                    	push	ax
  1953 000016CC 88E3                    	mov	bl, ah
  1954 000016CE C0EB04                  	shr	bl, 4
  1955 000016D1 8A83[FC160000]          	mov	al, [ebx+hexchrs] 	 	
  1956 000016D7 88E3                    	mov	bl, ah
  1957 000016D9 80E30F                  	and	bl, 0Fh
  1958 000016DC 8AA3[FC160000]          	mov	ah, [ebx+hexchrs]
  1959 000016E2 C1E010                  	shl	eax, 16
  1960 000016E5 6658                    	pop	ax
  1961 000016E7 5B                      	pop	ebx
  1962 000016E8 EBC0                    	jmp	short bytetohex
  1963                                  	;mov	bl, al
  1964                                  	;shr	bl, 4
  1965                                  	;mov	bl, [ebx+hexchrs] 	 	
  1966                                  	;xchg	bl, al	 	
  1967                                  	;and	bl, 0Fh
  1968                                  	;mov	ah, [ebx+hexchrs] 
  1969                                  	;pop	ebx	
  1970                                  	;retn
  1971                                  
  1972                                  dwordtohex:
  1973                                  	; INPUT ->
  1974                                  	; 	EAX = dword (binary number)
  1975                                  	; OUTPUT ->
  1976                                  	;	EDX:EAX = hexadecimal string
  1977                                  	;
  1978 000016EA 50                      	push	eax
  1979 000016EB C1E810                  	shr	eax, 16
  1980 000016EE E8D2FFFFFF              	call	wordtohex
  1981 000016F3 89C2                    	mov	edx, eax
  1982 000016F5 58                      	pop	eax
  1983 000016F6 E8CAFFFFFF              	call	wordtohex
  1984 000016FB C3                      	retn
  1985                                  
  1986                                  ; 10/05/2015
  1987                                  hex_digits:
  1988                                  hexchrs:
  1989 000016FC 303132333435363738-     	db '0123456789ABCDEF'
  1989 00001705 39414243444546     
  1990                                  
  1991                                  ; Convert binary number to decimal/numeric string
  1992                                  ; 06/11/2014
  1993                                  ; Temporary Code
  1994                                  ;
  1995                                  
  1996                                  bintdstr:
  1997                                  	; EAX = binary number
  1998                                  	; ESI = decimal/numeric string address
  1999                                  	; EBX = divisor (10)
  2000                                  	; ECX = string length (<=10)
  2001 0000170C 01CE                    	add	esi, ecx
  2002                                  btdstr0:
  2003 0000170E 4E                      	dec	esi
  2004 0000170F 31D2                    	xor	edx, edx
  2005 00001711 F7F3                    	div	ebx
  2006 00001713 80C230                  	add	dl, 30h
  2007 00001716 8816                    	mov	[esi], dl
  2008 00001718 FEC9                    	dec	cl
  2009 0000171A 740C                    	jz	btdstr2
  2010 0000171C 09C0                    	or	eax, eax
  2011 0000171E 75EE                    	jnz	short btdstr0
  2012                                  btdstr1:
  2013 00001720 4E                      	dec	esi
  2014 00001721 C60620                          mov     byte [esi], 20h ; blank space
  2015 00001724 FEC9                    	dec	cl
  2016 00001726 75F8                    	jnz	short btdstr1
  2017                                  btdstr2:
  2018 00001728 C3                      	retn
  2019                                  
  2020                                  ; Calculate free memory pages on M.A.T.
  2021                                  ; 06/11/2014
  2022                                  ; Temporary Code
  2023                                  ;
  2024                                  
  2025                                  calc_free_mem:
  2026 00001729 31D2                    	xor	edx, edx
  2027                                  	;xor	ecx, ecx
  2028 0000172B 668B0D[20630000]        	mov	cx, [mat_size] ; in pages
  2029 00001732 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2030 00001735 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2031                                  cfm0:
  2032 0000173A AD                      	lodsd
  2033 0000173B 51                      	push	ecx
  2034 0000173C B920000000              	mov	ecx, 32
  2035                                  cfm1:
  2036 00001741 D1E8                    	shr	eax, 1
  2037 00001743 7301                    	jnc	short cfm2
  2038 00001745 42                      	inc	edx
  2039                                  cfm2:
  2040 00001746 E2F9                    	loop	cfm1
  2041 00001748 59                      	pop	ecx
  2042 00001749 E2EF                    	loop	cfm0
  2043 0000174B C3                      	retn
  2044                                  
  2045                                  %include 'diskio.inc'  ; 07/03/2015
  2046                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKIO.INC
  2047                              <1> ; Last Modification: 12/07/2022
  2048                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2049                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2050                              <1> ; ************************************************************************
  2051                              <1> ; Ref: Retro UNIX 386 v1.1 'diskio.inc' modification: 12/07/2022
  2052                              <1> 
  2053                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2054                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2055                              <1> 
  2056                              <1> ; 06/02/2015
  2057                              <1> diskette_io:
  2058 0000174C 9C                  <1> 	pushfd
  2059 0000174D 0E                  <1> 	push 	cs
  2060 0000174E E801000000          <1> 	call 	DISKETTE_IO_1
  2061 00001753 C3                  <1> 	retn
  2062                              <1> 	
  2063                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2064                              <1> ;//////////////////////////////////////////////////////
  2065                              <1> 
  2066                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2067                              <1> ;		Function in AL
  2068                              <1> ;			0 = reset
  2069                              <1> ;			1 = read
  2070                              <1> ;			2 = write
  2071                              <1> ;		Disk drive number in DL
  2072                              <1> ;			0 & 1 = floppy disks	
  2073                              <1> ;			80h .. 83h = hard disks
  2074                              <1> ;		Sector address (LBA) in ECX
  2075                              <1> ;		Buffer address in EBX
  2076                              <1> ;		R/W sector count is (always) 1
  2077                              <1> ;
  2078                              <1> ;		Return:
  2079                              <1> ;			Status in AH (>0 = error code)
  2080                              <1> ;			if CF = 1 -> error code in AH
  2081                              <1> ;			if CF = 0 -> successful
  2082                              <1> ;			AL = undefined
  2083                              <1> ;
  2084                              <1> ;		Modified registers: (only) EAX
  2085                              <1> 
  2086                              <1> ; 10/07/2022
  2087                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2088                              <1> ;		by removing unused IBM PC-AT disk functions)
  2089                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2090                              <1> ; 20/02/2015
  2091                              <1> ; 06/02/2015 (unix386.s)
  2092                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2093                              <1> ;
  2094                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2095                              <1> ;
  2096                              <1> ; ADISK.EQU
  2097                              <1> 
  2098                              <1> ;----- Wait control constants 
  2099                              <1> 
  2100                              <1> ;amount of time to wait while RESET is active.
  2101                              <1> 
  2102                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2103                              <1> 					;at 250 KBS xfer rate.
  2104                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2105                              <1> 
  2106                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2107                              <1> 					;status register to become valid
  2108                              <1> 					;before re-reading.
  2109                              <1> 
  2110                              <1> ;After sending a byte to NEC, status register may remain
  2111                              <1> ;incorrectly set for 24 us.
  2112                              <1> 
  2113                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2114                              <1> 					;RQM low.
  2115                              <1> 
  2116                              <1> ; COMMON.MAC
  2117                              <1> ;
  2118                              <1> ;	Timing macros
  2119                              <1> ;
  2120                              <1> 
  2121                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2122                              <1> 		jmp short $+2
  2123                              <1> %endmacro		
  2124                              <1> 
  2125                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2126                              <1> 		jmp short $+2
  2127                              <1> 		jmp short $+2
  2128                              <1> %endmacro
  2129                              <1> 
  2130                              <1> %macro		NEWIODELAY 0
  2131                              <1> 		out	0EBh,al
  2132                              <1> %endmacro 
  2133                              <1> 
  2134                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2135                              <1> ;;; WAIT_FOR_MEM
  2136                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2137                              <1> ;WAIT_FDU_INT_HI	equ	1
  2138                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2139                              <1> ;;; WAIT_FOR_PORT
  2140                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2141                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2142                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2143                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2144                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2145                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2146                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2147                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2148                              <1> ;;; WAIT_REFRESH
  2149                              <1> ;amount of time to wait for head settle, per unit in parameter
  2150                              <1> ;table = 1 ms.
  2151                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2152                              <1> 
  2153                              <1> 
  2154                              <1> ; //////////////// DISKETTE I/O ////////////////
  2155                              <1> 
  2156                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2157                              <1> 
  2158                              <1> ;----------------------------------------
  2159                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2160                              <1> ;----------------------------------------
  2161                              <1> 
  2162                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2163                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2164                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2165                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2166                              <1> 
  2167                              <1> ;----------------------------------------
  2168                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2169                              <1> ;-------------------------------------------------------------------------------
  2170                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2171                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2172                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2173                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2174                              <1> 
  2175                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2176                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2177                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2178                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2179                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2180                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2181                              <1> 
  2182                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2183                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2184                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2185                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2186                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2187                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2188                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2189                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2190                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2191                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2192                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2193                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2194                              <1> 
  2195                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2196                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2197                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2198                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2199                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2200                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2201                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2202                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2203                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2204                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2205                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2206                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2207                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2208                              <1> 
  2209                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2210                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2211                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2212                              <1> 
  2213                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2214                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2215                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2216                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2217                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2218                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2219                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2220                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2221                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2222                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2223                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2224                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2225                              <1> 
  2226                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2227                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2228                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2229                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2230                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2231                              <1> 
  2232                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2233                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2234                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2235                              <1> INTA01		EQU	021H		; 8259 PORT
  2236                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2237                              <1> INTB01		EQU	0A1H		;
  2238                              <1> 
  2239                              <1> ;-------------------------------------------------------------------------------
  2240                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2241                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2242                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2243                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2244                              <1> ;-------------------------------------------------------------------------------
  2245                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2246                              <1> 
  2247                              <1> ;-------------------------------------------------------------------------------
  2248                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2249                              <1> 
  2250                              <1> ; 10/07/2022
  2251                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2252                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2253                              <1> ; (unix386.s <-- dsectrm2.s)
  2254                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2255                              <1> 
  2256                              <1> ; 10/12/2014
  2257                              <1> ;
  2258                              <1> ;int40h:
  2259                              <1> ;	pushf
  2260                              <1> ;	push 	cs
  2261                              <1> ;	;cli
  2262                              <1> ;	call 	DISKETTE_IO_1
  2263                              <1> ;	retn
  2264                              <1> 
  2265                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2266                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2267                              <1> ;
  2268                              <1> 
  2269                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2270                              <1> ; DISKETTE I/O
  2271                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2272                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2273                              <1> ; INPUT
  2274                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2275                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2276                              <1> ;		ON ALL DRIVES
  2277                              <1> ;------------------------------------------------------------------------------- 
  2278                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2279                              <1> ;-------------------------------------------------------------------------------
  2280                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2281                              <1> ;-------------------------------------------------------------------------------
  2282                              <1> ;
  2283                              <1> ;	REGISTERS FOR READ/WRITE
  2284                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2285                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2286                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2287                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2288                              <1> ;		320/360	320/360	    0-39
  2289                              <1> ;		320/360	1.2M	    0-39
  2290                              <1> ;		1.2M	1.2M	    0-79
  2291                              <1> ;		720K	720K	    0-79
  2292                              <1> ;		1.44M	1.44M	    0-79	
  2293                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2294                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2295                              <1> ;		320/360	320/360	     1-8/9
  2296                              <1> ;		320/360	1.2M	     1-8/9
  2297                              <1> ;		1.2M	1.2M	     1-15
  2298                              <1> ;		720K	720K	     1-9
  2299                              <1> ;		1.44M	1.44M	     1-18		
  2300                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2301                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2302                              <1> ;		320/360	320/360	        8/9
  2303                              <1> ;		320/360	1.2M	        8/9
  2304                              <1> ;		1.2M	1.2M		15
  2305                              <1> ;		720K	720K		9
  2306                              <1> ;		1.44M	1.44M		18
  2307                              <1> ;
  2308                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2309                              <1> ;
  2310                              <1> ;-------------------------------------------------------------------------------
  2311                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2312                              <1> ;	AH = STATUS OF OPERATION
  2313                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2314                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2315                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2316                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2317                              <1> ;	FOR READ/WRITE/VERIFY
  2318                              <1> ;		DS,BX,DX,CX PRESERVED
  2319                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2320                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2321                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2322                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2323                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2324                              <1> ;-------------------------------------------------------------------------------
  2325                              <1> ;
  2326                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2327                              <1> ;
  2328                              <1> ;   -----------------------------------------------------------------
  2329                              <1> ;   |       |       |       |       |       |       |       |       |
  2330                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2331                              <1> ;   |       |       |       |       |       |       |       |       |
  2332                              <1> ;   -----------------------------------------------------------------
  2333                              <1> ;	|	|	|	|	|	|	|	|
  2334                              <1> ;	|	|	|	|	|	-----------------
  2335                              <1> ;	|	|	|	|	|		|
  2336                              <1> ;	|	|	|	|    RESERVED		|
  2337                              <1> ;	|	|	|	|		  PRESENT STATE
  2338                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2339                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2340                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2341                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2342                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2343                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2344                              <1> ;	|	|	|	|	110: RESERVED
  2345                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2346                              <1> ;	|	|	|	|
  2347                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2348                              <1> ;	|	|	|
  2349                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2350                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2351                              <1> ;	|	|
  2352                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2353                              <1> ;
  2354                              <1> ;						00: 500 KBS
  2355                              <1> ;						01: 300 KBS
  2356                              <1> ;						10: 250 KBS
  2357                              <1> ;						11: RESERVED
  2358                              <1> ;
  2359                              <1> ;
  2360                              <1> 
  2361                              <1> struc MD
  2362 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2363 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2364 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2365 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2366 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2367 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2368 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2369 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2370 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2371 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2372 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2373 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2374 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2375                              <1> endstruc
  2376                              <1> 
  2377                              <1> BIT7OFF	EQU	7FH
  2378                              <1> BIT7ON	EQU	80H
  2379                              <1> 
  2380                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2381                              <1> ;		Function in AL
  2382                              <1> ;			0 = reset
  2383                              <1> ;			1 = read
  2384                              <1> ;			2 = write
  2385                              <1> ;		Disk drive number in DL
  2386                              <1> ;			0 & 1 = floppy disks	
  2387                              <1> ;			80h .. 83h = hard disks
  2388                              <1> ;		Sector address (LBA) in ECX
  2389                              <1> ;		Buffer address in EBX
  2390                              <1> ;		R/W sector count is (always) 1
  2391                              <1> ;
  2392                              <1> ;		Return:
  2393                              <1> ;			Status in AH (>0 = error code)
  2394                              <1> ;			if CF = 1 -> error code in AH
  2395                              <1> ;			if CF = 0 -> successful
  2396                              <1> ;			AL = undefined
  2397                              <1> ;
  2398                              <1> ;		Modified registers: (only) EAX
  2399                              <1> 
  2400                              <1> ; 11/07/2022
  2401                              <1> ;;int13h: ; 16/02/2015
  2402                              <1> ;; 16/02/2015 - 21/02/2015
  2403                              <1> ;int40h:
  2404                              <1> ;	pushfd
  2405                              <1> ;	push 	cs
  2406                              <1> ;	call 	DISKETTE_IO_1
  2407                              <1> ;	retn	
  2408                              <1> 
  2409                              <1> DISKETTE_IO_1:
  2410                              <1> 
  2411                              <1> 	;sti				; INTERRUPTS BACK ON
  2412                              <1> 	; 11/07/2022
  2413                              <1> 	; save registers
  2414 00001754 55                  <1> 	push	ebp			; ANY
  2415                              <1> 
  2416                              <1> 	; 11/07/2022
  2417                              <1> 	;push	edi			; ANY
  2418                              <1> 	;push	edx			; DRIVE NUMBER (DL)
  2419                              <1> 	;push	ebx			; BUFFER ADDRESS
  2420                              <1> 	;push	ecx			; SECTOR ADDRESS (LBA)
  2421                              <1> 	;push	esi			; ANY
  2422                              <1> 
  2423                              <1> 	; 11/07/2022
  2424 00001755 89DD                <1> 	mov	ebp, ebx ; buffer address
  2425 00001757 C605[8C630000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS
  2426 0000175E 0FB6FA              <1> 	movzx	edi, dl ; drive number (0 or 1)
  2427                              <1> 	
  2428 00001761 08C0                <1> 	or	al, al			; RESET ?
  2429 00001763 7507                <1> 	jnz	short DISKETTE_RW_1	; NO
  2430                              <1> 
  2431 00001765 E84F010000          <1> 	call	DSK_RESET
  2432                              <1> 
  2433 0000176A EB37                <1> 	jmp	short DISKETTE_RW_2	
  2434                              <1> 
  2435                              <1> DISKETTE_RW_1:
  2436                              <1> 	; 12/07/2022
  2437                              <1> 	; 11/07/2022
  2438                              <1> 	; ecx = sector address (LBA, < 2880)
  2439                              <1> 	; ebp = buffer address
  2440                              <1> 	; edi = drive number (0 or 1)
  2441                              <1> 	;  al = function (read = 1 or write = 2)
  2442                              <1> 
  2443 0000176C 88C2                <1> 	mov	dl, al ; *
  2444                              <1> convert_to_chs:
  2445                              <1> 	;;;
  2446 0000176E B004                <1> 	mov	al, 4 ; MD.SEC_TRK ; sector per track (drv.spt)
  2447 00001770 E8F2050000          <1> 	call	GET_PARM
  2448                              <1> 	; 12/07/2022
  2449 00001775 88E6                <1> 	mov	dh, ah ; spt
  2450 00001777 89C8                <1> 	mov	eax, ecx ; sector address (LBA) 
  2451 00001779 F6F6                <1> 	div	dh  ; AX/DH
  2452 0000177B 88E1                <1> 	mov	cl, ah ; sector number - 1
  2453 0000177D FEC1                <1> 	inc	cl  ; sector number (1 based)
  2454 0000177F 28ED                <1> 	sub	ch, ch ; head = 0 
  2455                              <1> 	; heads = 2
  2456 00001781 D0E8                <1> 	shr	al, 1 ; al = al/2
  2457 00001783 80D500              <1> 	adc	ch, 0 ; head = 1 or head = 0
  2458 00001786 C1E110              <1> 	shl	ecx, 16
  2459 00001789 88C1                <1> 	mov	cl, al ; track (cylinder)
  2460 0000178B 88D5                <1> 	mov	ch, dl ; function number 
  2461 0000178D 89CE                <1> 	mov	esi, ecx ; byte 0 = track, byte 1 = function
  2462                              <1> 			 ; byte 2 = sector, byte 3 = head
  2463 0000178F C1C610              <1> 	rol	esi, 16
  2464                              <1> 			 ; byte 0 = sector, byte 1 = head
  2465                              <1> 			 ; byte 2 = track, byte 3 = function		
  2466                              <1> 	;;; 
  2467 00001792 80FA02              <1> 	cmp	dl, 2 ; *
  2468 00001795 7407                <1> 	je	short DISKETTE_W
  2469                              <1> DISKETTE_R:	
  2470                              <1> 	; dl = 1 ; *
  2471 00001797 E809000000          <1> 	call	DSK_READ
  2472 0000179C EB05                <1> 	jmp	short DISKETTE_RW_2
  2473                              <1> DISKETTE_W:
  2474 0000179E E80F000000          <1> 	call	DSK_WRITE
  2475                              <1> DISKETTE_RW_2:
  2476                              <1> 	; 11/07/2022
  2477                              <1> 	; Restore registers
  2478                              <1> 	;pop	esi
  2479                              <1> 	;pop	ecx
  2480                              <1> 	;pop	ebx
  2481                              <1> 	;pop	edx
  2482                              <1> 	;pop	edi
  2483                              <1> 
  2484                              <1> 	; 11/07/2022
  2485 000017A3 5D                  <1> 	pop	ebp
  2486 000017A4 C3                  <1> 	retn
  2487                              <1> 
  2488                              <1> ;-------------------------------------------------------------------------------
  2489                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2490                              <1> ;	DISKETTE READ.
  2491                              <1> ;
  2492                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2493                              <1> ;		SI-HI	: HEAD #
  2494                              <1> ;		SI-LOW	: # OF SECTORS
  2495                              <1> ;		ES	: BUFFER SEGMENT
  2496                              <1> ;		[BP]	: SECTOR #
  2497                              <1> ;		[BP+1]	: TRACK #
  2498                              <1> ;		[BP+2]	: BUFFER OFFSET
  2499                              <1> ;
  2500                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2501                              <1> ;-------------------------------------------------------------------------------
  2502                              <1> 
  2503                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2504                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2505                              <1> 
  2506                              <1> DSK_READ:
  2507 000017A5 8025[8A630000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2508 000017AC 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2509                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2510                              <1> 	;retn
  2511 000017B0 EB0B                <1> 	jmp	short RD_WR_VF
  2512                              <1> 
  2513                              <1> ;-------------------------------------------------------------------------------
  2514                              <1> ; DISK_WRITE	(AH = 02H)
  2515                              <1> ;	DISKETTE WRITE.
  2516                              <1> ;
  2517                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2518                              <1> ;		SI-HI	: HEAD #
  2519                              <1> ;		SI-LOW	: # OF SECTORS
  2520                              <1> ;		ES	: BUFFER SEGMENT
  2521                              <1> ;		[BP]	: SECTOR #
  2522                              <1> ;		[BP+1]	: TRACK #
  2523                              <1> ;		[BP+2]	: BUFFER OFFSET
  2524                              <1> ;
  2525                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2526                              <1> ;-------------------------------------------------------------------------------
  2527                              <1> 
  2528                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2529                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2530                              <1> 
  2531                              <1> DSK_WRITE:
  2532 000017B2 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2533 000017B6 800D[8A630000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2534                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2535                              <1> 	;;retn
  2536                              <1> 	;jmp	short RD_WR_VF
  2537                              <1> 
  2538                              <1> ;-------------------------------------------------------------------------------
  2539                              <1> ; RD_WR_VF
  2540                              <1> ;	COMMON READ, WRITE
  2541                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2542                              <1> ;
  2543                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2544                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2545                              <1> ;
  2546                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2547                              <1> ;-------------------------------------------------------------------------------
  2548                              <1> 
  2549                              <1> RD_WR_VF:
  2550                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2551 000017BD 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2552 000017BE E8CF010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2553 000017C3 E831020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2554 000017C8 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2555                              <1> DO_AGAIN:
  2556 000017C9 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2557 000017CA E86B020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2558 000017CF 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2559                              <1> 	; 24/12/2021
  2560 000017D0 7305                <1> 	jnc	short RWV
  2561 000017D2 E9B8000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2562                              <1> RWV:
  2563 000017D7 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2564 000017D8 8AB7[97630000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2565 000017DE 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2566 000017E1 E878050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2567                              <1> 	; 20/02/2015
  2568 000017E6 7445                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2569 000017E8 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2570 000017EA 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2571 000017EC F687[97630000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2572 000017F3 740F                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2573                              <1> 	;mov	al, 2			; CHANGE TO 1.2M
  2574                              <1> 	; 12/07/2022
  2575 000017F5 FEC0                <1> 	inc	al  ; al = 2
  2576 000017F7 EB0B                <1> 	jmp	short RWV_2
  2577                              <1> RWV_1:
  2578                              <1> 	; 12/07/2022
  2579                              <1> 	;jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2580 000017F9 F687[97630000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2581 00001800 7502                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2582 00001802 B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2583                              <1> 	; 12/07/2022
  2584                              <1> 	;jmp	short RWV_3
  2585                              <1> RWV_2:
  2586                              <1> 	; 12/07/2022
  2587                              <1> 	;or	al, al			; TEST FOR NO DRIVE
  2588                              <1> 	;jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2589                              <1> RWV_3:
  2590                              <1> 	; 12/07/2022
  2591                              <1> 	;mov	dl, al	; 11/07/2022
  2592 00001804 E823010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2593 00001809 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2594                              <1> 
  2595                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2596                              <1> 
  2597 0000180B 57                  <1> 	push	edi			; SAVE DRIVE #
  2598                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2599 0000180C BB[AC5D0000]        <1> 	mov	ebx, DR_TYPE
  2600                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2601 00001811 B106                <1> 	mov	cl, DR_CNT
  2602                              <1> RWV_DR_SEARCH:
  2603                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2604 00001813 8A23                <1> 	mov	ah, [ebx]
  2605 00001815 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2606 00001818 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2607                              <1> 	; 12/07/2022
  2608                              <1> 	;cmp	dl, ah ; 11/07/2022
  2609 0000181A 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2610                              <1> RWV_DR_FND:
  2611                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2612 0000181C 43                  <1> 	inc	ebx
  2613 0000181D 8B3B                <1> 	mov	edi, [ebx]
  2614 0000181F 4B                  <1> 	dec	ebx
  2615                              <1> RWV_MD_SEARH:
  2616 00001820 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2617 00001823 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2618                              <1> RWV_NXT_MD:
  2619 00001825 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2620                              <1> 	;loop	RWV_DR_SEARCH
  2621 00001828 FEC9                <1> 	dec	cl
  2622 0000182A 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2623 0000182C 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2624                              <1> 
  2625                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2626                              <1> 
  2627                              <1> RWV_ASSUME:
  2628 0000182D BB[CA5D0000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2629 00001832 F687[97630000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2630 00001839 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2631 0000183B BB[E45D0000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2632 00001840 EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2633                              <1> 
  2634                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2635                              <1> 	 			
  2636                              <1> RWV_MD_FND:
  2637 00001842 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2638 00001844 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2639                              <1> 	
  2640                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2641                              <1> 
  2642                              <1> RWV_MD_FND1:
  2643 00001845 E828010000          <1> 	call	SEND_SPEC_MD
  2644 0000184A E857020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2645 0000184F 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2646 00001851 E832020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2647                              <1> RWV_DBL:
  2648 00001856 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2649 00001857 E860040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2650 0000185C 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2651 0000185D 7223                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2652                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2653                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2654                              <1> 	; 08/07/2022
  2655 0000185F 8B0424              <1> 	mov	eax, [esp]
  2656 00001862 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2657 00001863 E851020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2658 00001868 5B                  <1> 	pop	ebx
  2659 00001869 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2660 0000186A 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2661 0000186C 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2662 0000186D 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2663 0000186E E8A3020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2664 00001873 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2665 00001874 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2666 00001876 E8CC020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2667 0000187B 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2668 0000187D E813030000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2669                              <1> CHK_RET:
  2670 00001882 E8B2030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2671 00001887 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2672 00001888 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2673 0000188A E93AFFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2674                              <1> RWV_END:
  2675 0000188F E85D030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2676 00001894 E8EE030000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2677                              <1> RWV_BAC:
  2678                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2679                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2680                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2681                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2682                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2683                              <1> 	;;retn
  2684                              <1> 	;jmp	SETUP_END
  2685                              <1> 
  2686                              <1> ;-------------------------------------------------------------------------------
  2687                              <1> ; SETUP_END
  2688                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2689                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2690                              <1> ;
  2691                              <1> ; ON EXIT:
  2692                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2693                              <1> ;-------------------------------------------------------------------------------
  2694                              <1> SETUP_END:
  2695                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2696                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2697                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2698 00001899 50                  <1> 	push	eax ; 24/12/2021
  2699 0000189A B002                <1> 	mov	al, 2 ; 08/07/2022
  2700 0000189C E8C6040000          <1> 	call	GET_PARM
  2701 000018A1 8825[8B630000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2702                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2703 000018A7 58                  <1> 	pop	eax ; 24/12/2021
  2704 000018A8 8A25[8C630000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2705 000018AE 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2706 000018B0 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2707 000018B2 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2708                              <1> ;NUN_ERR: 
  2709 000018B4 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2710 000018B7 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2711                              <1> NUN_ERR:
  2712 000018B8 C3                  <1> 	retn
  2713                              <1> 
  2714                              <1> ;-------------------------------------------------------------------------------
  2715                              <1> ; DISK_RESET	(AH = 00H)	
  2716                              <1> ;		RESET THE DISKETTE SYSTEM.
  2717                              <1> ;
  2718                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2719                              <1> ;-------------------------------------------------------------------------------
  2720                              <1> DSK_RESET:
  2721                              <1> 	; 12/07/2022
  2722                              <1> 	; 11/07/2022
  2723                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2724 000018B9 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2725 000018BD FA                  <1> 	cli				; NO INTERRUPTS
  2726 000018BE A0[8A630000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2727 000018C3 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2728 000018C5 C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2729                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2730 000018C8 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2731 000018CA EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2732 000018CB C605[89630000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2733                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2734                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2735                              <1> 					;      PULSE WIDTH)
  2736                              <1> 	; 19/12/2014
  2737                              <1> 	NEWIODELAY
  2131 000018D2 E6EB                <2>  out 0EBh,al
  2738                              <1> 
  2739                              <1> 	; 17/12/2014 
  2740                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2741 000018D4 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2742                              <1> wdw1:
  2743                              <1> 	NEWIODELAY   ; 27/02/2015
  2131 000018D9 E6EB                <2>  out 0EBh,al
  2744 000018DB E2FC                <1> 	loop	wdw1
  2745                              <1> 	;
  2746 000018DD 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2747 000018DF EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2748                              <1> 	; 16/12/2014
  2749                              <1> 	IODELAY
  2126 000018E0 EB00                <2>  jmp short $+2
  2127 000018E2 EB00                <2>  jmp short $+2
  2750                              <1> 	;
  2751                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2752 000018E4 E879060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2753 000018E9 7238                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2754                              <1> 	;mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2755                              <1> 	; 12/07/2022
  2756                              <1> 	;xor	ecx, ecx
  2757 000018EB 30ED                <1> 	xor	ch, ch
  2758 000018ED B1C0                <1> 	mov	cl, 11000000b
  2759                              <1> NXT_DRV:
  2760                              <1> 	; 24/12/2021
  2761 000018EF 51                  <1> 	push	ecx			; SAVE FOR CALL
  2762 000018F0 B8[22190000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2763 000018F5 50                  <1> 	push	eax			;
  2764 000018F6 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2765 000018F8 E85B050000          <1> 	call	NEC_OUTPUT
  2766 000018FD 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2767 000018FE E88E060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2768                              <1> 	; 24/12/2021
  2769 00001903 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2770 00001904 721D                <1> 	jc	short DR_ERR		; ERROR RETURN
  2771 00001906 3A0D[8D630000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2772 0000190C 7515                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2773 0000190E FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2774 00001910 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2775 00001913 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2776                              <1> 	;
  2777 00001915 E82F000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2778                              <1> RESBAC:
  2779 0000191A E87AFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2780                              <1> 	
  2781                              <1> 	; 11/07/2022
  2782                              <1> 	; CF = 1 -> error (error code in AH)
  2783                              <1> 	; CF = 0 -> OK
  2784                              <1> 	
  2785                              <1> 	;; 24/12/2021
  2786                              <1> 	;mov	ebx, esi		; GET SAVED AL TO BL
  2787                              <1> 	;; 11/07/2022
  2788                              <1> 	;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 
  2789                              <1> 	;rol	ebx, 8
  2790                              <1> 	; bl = function (reset = 0)
  2791                              <1> 	;
  2792                              <1> 	;mov	al, bl			; PUT BACK FOR RETURN
  2793                              <1> 	
  2794                              <1> 	; 11/07/2022  
  2795 0000191F B000                <1> 	mov	al, 0	; (reset function = 0)
  2796                              <1> 
  2797 00001921 C3                  <1> 	retn
  2798                              <1> 
  2799                              <1> DR_POP_ERR:
  2800                              <1> 	; 24/12/2021
  2801 00001922 59                  <1> 	pop	ecx			; CLEAR STACK
  2802                              <1> DR_ERR:
  2803 00001923 800D[8C630000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2804 0000192A EBEE                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2805                              <1> 
  2806                              <1> ;-------------------------------------------------------------------------------
  2807                              <1> ; FNC_ERR
  2808                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2809                              <1> ;	SET BAD COMMAND IN STATUS.
  2810                              <1> ;
  2811                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2812                              <1> ;-------------------------------------------------------------------------------
  2813                              <1> 
  2814                              <1> 	; 11/07/2022 - not needed (because diskio is used by kernel only)
  2815                              <1> 	
  2816                              <1> ;FNC_ERR:				; INVALID FUNCTION REQUEST
  2817                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2818                              <1> ;	; 24/12/2021
  2819                              <1> ;	mov	eax, esi		; RESTORE AL
  2820                              <1> ;	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2821                              <1> ;	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2822                              <1> ;	stc				; SET CARRY INDICATING ERROR
  2823                              <1> ;	retn
  2824                              <1> 
  2825                              <1> 
  2826                              <1> ;----------------------------------------------------------------
  2827                              <1> ; DR_TYPE_CHECK							:
  2828                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2829                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2830                              <1> ; ON ENTRY:							:
  2831                              <1> ;	AL = DRIVE TYPE						:
  2832                              <1> ; ON EXIT:							:
  2833                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2834                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2835                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2836                              <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 			:
  2837                              <1> ;----------------------------------------------------------------
  2838                              <1> DR_TYPE_CHECK:
  2839                              <1> 	; 12/07/2022
  2840                              <1> 	; 11/07/2022
  2841                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2842                              <1> 	; 24/12/2021
  2843                              <1> 	;push	eax ; 11/07/2022
  2844                              <1> 	;push	ecx ; 08/07/2022
  2845                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2846 0000192C BB[AC5D0000]        <1> 	mov	ebx, DR_TYPE
  2847                              <1> 	;;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2848                              <1> 	;mov	cl, DR_CNT
  2849 00001931 B406                <1> 	mov	ah, DR_CNT ; 11/07/2022
  2850                              <1> TYPE_CHK:	
  2851                              <1> 	;;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2852                              <1> 	;mov	ah, [ebx]
  2853                              <1> 	;cmp	al, ah			; DRIVE TYPE MATCH?
  2854 00001933 3A03                <1> 	cmp	al, [ebx] ; 11/07/2022
  2855 00001935 740E                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2856                              <1> 	; 16/02/2015 (32 bit address modification)
  2857 00001937 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2858                              <1> 	;loop	TYPE_CHK
  2859                              <1> 	;dec	cl
  2860 0000193A FECC                <1> 	dec	ah ; 11/07/2022
  2861 0000193C 75F5                <1> 	jnz	short TYPE_CHK
  2862                              <1> 	;
  2863 0000193E BB[0B5E0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2864                              <1> 					; Default for GET_PARM (11/12/2014)
  2865                              <1> 	;
  2866 00001943 F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2867                              <1> 	;jmp	short TYPE_RTN
  2868                              <1> 	; 12/07/2022
  2869 00001944 C3                  <1> 	retn
  2870                              <1> DR_TYPE_VALID:
  2871                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2872 00001945 43                  <1> 	inc	ebx
  2873 00001946 8B1B                <1> 	mov	ebx, [ebx]
  2874                              <1> TYPE_RTN:
  2875                              <1> 	;pop	ecx ; 08/07/2022
  2876                              <1> 	; 24/12/2021
  2877                              <1> 	;pop	eax ; 11/07/2022
  2878 00001948 C3                  <1> 	retn		
  2879                              <1> 
  2880                              <1> ;----------------------------------------------------------------
  2881                              <1> ; SEND_SPEC							:
  2882                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2883                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2884                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2885                              <1> ; ON EXIT:	NONE						:	
  2886                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2887                              <1> ;----------------------------------------------------------------		
  2888                              <1> SEND_SPEC:
  2889                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2890 00001949 50                  <1> 	push	eax			; SAVE EAX
  2891 0000194A B8[70190000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2892 0000194F 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2893 00001950 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2894 00001952 E801050000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2895                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2896 00001957 28C0                <1> 	sub	al, al ; 08/07/2022
  2897 00001959 E809040000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2898 0000195E E8F5040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2899                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2900 00001963 B001                <1> 	mov	al, 1 ; 08/07/2022
  2901 00001965 E8FD030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2902 0000196A E8E9040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2903 0000196F 58                  <1> 	pop	eax			; POP ERROR RETURN
  2904                              <1> SPECBAC:
  2905 00001970 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2906 00001971 C3                  <1> 	retn
  2907                              <1> 
  2908                              <1> ;----------------------------------------------------------------
  2909                              <1> ; SEND_SPEC_MD							:
  2910                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2911                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  2912                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  2913                              <1> ; ON EXIT:	NONE						:	
  2914                              <1> ; REGISTERS ALTERED: AX						:
  2915                              <1> ;----------------------------------------------------------------		
  2916                              <1> SEND_SPEC_MD:
  2917 00001972 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  2918 00001973 B8[90190000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2919 00001978 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2920 00001979 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  2921 0000197B E8D8040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2922 00001980 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2923 00001982 E8D1040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2924 00001987 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2925 0000198A E8C9040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2926 0000198F 58                  <1> 	POP	eAX			; POP ERROR RETURN
  2927                              <1> SPEC_ESBAC:
  2928 00001990 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  2929 00001991 C3                  <1> 	RETn
  2930                              <1> 
  2931                              <1> ;-------------------------------------------------------------------------------
  2932                              <1> ; XLAT_NEW  
  2933                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  2934                              <1> ;	MODE TO NEW ARCHITECTURE.
  2935                              <1> ;
  2936                              <1> ; ON ENTRY:	EDI = DRIVE #
  2937                              <1> ;-------------------------------------------------------------------------------
  2938                              <1> XLAT_NEW:
  2939                              <1> 	; 11/07/2022
  2940                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2941                              <1> 	;cmp	edi, 1				; VALID DRIVE
  2942                              <1> 	;ja	short XN_OUT			; IF INVALID BACK
  2943                              <1> 	;
  2944 00001992 80BF[97630000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  2945 00001999 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  2946                              <1> 	;
  2947                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2948                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  2949                              <1> 	;or	cl, cl
  2950                              <1> 	;jz	short XN_0  ; 08/07/2022
  2951                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  2952                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2953                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  2954                              <1> ;XN_0:	
  2955                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  2956                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  2957                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  2958                              <1> XN_OUT:
  2959 0000199B C3                  <1> 	retn
  2960                              <1> DO_DET:
  2961                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  2962                              <1> 	;;retn
  2963                              <1> 	;jmp	DRIVE_DET
  2964                              <1> 
  2965                              <1> ;-------------------------------------------------------------------------------
  2966                              <1> ; DRIVE_DET
  2967                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  2968                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  2969                              <1> ; ON ENTRY:	EDI = DRIVE #
  2970                              <1> ;-------------------------------------------------------------------------------
  2971                              <1> DRIVE_DET:
  2972                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2973 0000199C E801040000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  2974 000019A1 E86A050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  2975 000019A6 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  2976 000019A8 B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  2977 000019AA E8E2040000          <1> 	call	SEEK
  2978 000019AF 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  2979 000019B1 B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  2980                              <1> SK_GIN:
  2981 000019B3 FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  2982                              <1> 	;push	cx		
  2983                              <1> 	; 24/12/2021
  2984 000019B5 51                  <1> 	push	ecx			; SAVE TRACK
  2985 000019B6 E8D6040000          <1> 	call	SEEK
  2986 000019BB 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  2987 000019BD B8[F7190000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  2988 000019C2 50                  <1> 	push	eax
  2989 000019C3 B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  2990 000019C5 E88E040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2991                              <1> 	; 08/07/2022
  2992 000019CA 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  2993 000019CC 88C4                <1> 	mov	ah, al			; AH = DRIVE
  2994 000019CE E885040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2995 000019D3 E8B9050000          <1> 	call	RESULTS			; GO GET STATUS
  2996 000019D8 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  2997                              <1> 	;pop	cx			; RESTORE TRACK
  2998                              <1> 	; 24/12/2021
  2999 000019D9 59                  <1> 	pop	ecx
  3000 000019DA F605[8D630000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  3001 000019E1 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  3002 000019E3 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  3003 000019E5 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  3004                              <1> 
  3005                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  3006                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  3007                              <1> 
  3008 000019E7 808F[97630000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  3009 000019EE C3                  <1> 	retn				; ALL INFORMATION SET
  3010                              <1> IS_80:
  3011 000019EF 808F[97630000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3012                              <1> DD_BAC:
  3013 000019F6 C3                  <1> 	retn
  3014                              <1> POP_BAC:
  3015                              <1> 	;pop	cx			; THROW AWAY
  3016                              <1> 	; 24/12/2021
  3017 000019F7 59                  <1> 	pop	ecx
  3018 000019F8 C3                  <1> 	retn
  3019                              <1> 
  3020                              <1> ;-------------------------------------------------------------------------------
  3021                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3022                              <1> ;-------------------------------------------------------------------------------
  3023                              <1> SETUP_STATE:
  3024                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3025 000019F9 F687[97630000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3026 00001A00 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3027 00001A02 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3028 00001A06 F687[97630000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3029 00001A0D 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3030 00001A0F F687[97630000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3031 00001A16 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3032 00001A18 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3033                              <1> AX_SET:	
  3034 00001A1C 80A7[97630000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3035 00001A23 08A7[97630000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3036 00001A29 8025[94630000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3037 00001A30 C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3038 00001A33 0805[94630000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3039                              <1> J1C:	
  3040 00001A39 C3                  <1> 	retn
  3041                              <1> 
  3042                              <1> ;-------------------------------------------------------------------------------
  3043                              <1> ; MED_CHANGE	
  3044                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3045                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3046                              <1> ;
  3047                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3048                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3049                              <1> ;-------------------------------------------------------------------------------
  3050                              <1> MED_CHANGE:
  3051                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3052 00001A3A E8AA050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3053 00001A3F 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3054 00001A41 80A7[97630000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3055                              <1> 
  3056                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3057                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3058                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3059                              <1> 
  3060 00001A48 89F9                <1> 	mov	ecx, edi		; CL = DRIVE #
  3061 00001A4A B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3062 00001A4C D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3063 00001A4E F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3064 00001A50 FA                  <1> 	cli				; NO INTERRUPTS
  3065 00001A51 2005[8A630000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3066 00001A57 FB                  <1> 	sti				; INTERRUPTS ENABLED
  3067 00001A58 E845030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3068                              <1> 
  3069                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3070                              <1> 
  3071 00001A5D E857FEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3072 00001A62 B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3073 00001A64 E828040000          <1> 	call	SEEK			; ISSUE SEEK
  3074 00001A69 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3075 00001A6B E821040000          <1> 	call	SEEK			; ISSUE SEEK
  3076 00001A70 C605[8C630000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3077                              <1> OK1:
  3078 00001A77 E86D050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3079 00001A7C 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3080                              <1> OK4:
  3081 00001A7E C605[8C630000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3082                              <1> OK2:		
  3083 00001A85 F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3084 00001A86 C3                  <1> 	retn
  3085                              <1> MC_OUT:
  3086                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3087 00001A87 C3                  <1> 	retn
  3088                              <1> 
  3089                              <1> ;-------------------------------------------------------------------------------
  3090                              <1> ; SEND_RATE
  3091                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3092                              <1> ; ON ENTRY:	EDI = DRIVE #
  3093                              <1> ; ON EXIT:	NONE
  3094                              <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022
  3095                              <1> ;-------------------------------------------------------------------------------
  3096                              <1> SEND_RATE:
  3097                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5
  3098                              <1> 	;push	ax			; SAVE REG.
  3099                              <1> 	; 24/12/2021
  3100                              <1> 	;push	eax ; 11/07/2022
  3101 00001A88 8025[94630000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3102 00001A8F 8A87[97630000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3103 00001A95 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3104 00001A97 0805[94630000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3105 00001A9D C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3106 00001AA0 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3107 00001AA4 EE                  <1> 	out	dx, al
  3108                              <1> 	;pop	ax			; RESTORE REG.
  3109                              <1> 	; 24/12/2021
  3110                              <1> 	;pop	eax ; 11/07/2022
  3111 00001AA5 C3                  <1> 	retn
  3112                              <1> 
  3113                              <1> ;-------------------------------------------------------------------------------
  3114                              <1> ; CHK_LASTRATE
  3115                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3116                              <1> ; ON ENTRY:
  3117                              <1> ;	EDI = DRIVE #
  3118                              <1> ; ON EXIT:
  3119                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3120                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3121                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022
  3122                              <1> ;-------------------------------------------------------------------------------
  3123                              <1> CHK_LASTRATE:
  3124                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3125                              <1> 	;push	ax			; SAVE REG.
  3126                              <1> 	; 24/12/2021
  3127                              <1> 	;push	eax ; 11/07/2022
  3128 00001AA6 8A25[94630000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3129                              <1> 					; GET LAST DATA RATE SELECTED
  3130 00001AAC 8A87[97630000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3131 00001AB2 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3132 00001AB6 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3133                              <1> 					; ZF = 1 RATE IS THE SAME
  3134                              <1> 	;pop	ax			; RESTORE REG.
  3135                              <1> 	; 24/12/2021
  3136                              <1> 	;pop	eax ; 11/07/2022
  3137 00001AB8 C3                  <1> 	retn
  3138                              <1> 
  3139                              <1> ;-------------------------------------------------------------------------------
  3140                              <1> ; DMA_SETUP
  3141                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3142                              <1> ;
  3143                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3144                              <1> ;
  3145                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3146                              <1> ;-------------------------------------------------------------------------------
  3147                              <1> 
  3148                              <1> ; SI = Head #, # of Sectors or DASD Type
  3149                              <1> 
  3150                              <1> ; 22/08/2015
  3151                              <1> ; 08/02/2015 - Protected Mode Modification
  3152                              <1> ; 06/02/2015 - 07/02/2015
  3153                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3154                              <1> ; (DMA Addres = Physical Address)
  3155                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3156                              <1> ;
  3157                              <1> ; 04/02/2016 (clc)
  3158                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3159                              <1> ; 16/12/2014 (IODELAY)
  3160                              <1> 
  3161                              <1> DMA_SETUP:
  3162                              <1> 	; 11/07/2022
  3163                              <1> 	;	ebp = buffer address
  3164                              <1> 	
  3165                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3166                              <1> 	;; 20/02/2015
  3167                              <1> 	;mov	edx, [ebp+4] ; 11/07/2022 ; Buffer address
  3168                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3169                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3170                              <1> 	;jnz	short dma_bnd_err_stc
  3171                              <1> 	; 24/12/2021
  3172 00001AB9 50                  <1> 	push	eax			; DMA command
  3173                              <1> 	;push	edx ; 11/07/2022	; *
  3174                              <1> 	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3175 00001ABA B003                <1> 	mov	al, 3 ; 08/07/2022
  3176 00001ABC E8A6020000          <1> 	call	GET_PARM		; 
  3177 00001AC1 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3178                              <1> 	;mov	ax, si			; Sector count
  3179                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3180                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3181                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3182                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3183                              <1> 	; 08/07/2022
  3184                              <1> 	; 24/12/2021
  3185                              <1> 	;mov	edx, esi
  3186 00001AC3 29C0                <1> 	sub	eax, eax
  3187                              <1> 	;mov	ah, dl
  3188                              <1> 	;shr	eax, 1
  3189 00001AC5 B080                <1> 	mov	al, 128
  3190 00001AC7 D3E0                <1> 	shl	eax, cl
  3191                              <1> 	;
  3192 00001AC9 48                  <1> 	dec	eax			; -1 FOR DMA VALUE
  3193 00001ACA 89C1                <1> 	mov	ecx, eax
  3194                              <1> 	;pop	edx ; 11/07/2022	; *
  3195                              <1> 	; 24/12/2021
  3196 00001ACC 58                  <1> 	pop	eax
  3197                              <1> 	; 08/07/2022
  3198                              <1> 	;cmp	al, 42h
  3199                              <1>         ;jne	short NOT_VERF
  3200                              <1> 	;mov	edx, 0FF0000h
  3201                              <1> 	;jmp	short J33
  3202                              <1> ;NOT_VERF:
  3203                              <1> 	; 11/07/2022
  3204 00001ACD 89EA                <1> 	mov	edx, ebp
  3205                              <1> 	;
  3206 00001ACF 6601CA              <1> 	add	dx, cx			; check for (64K) overflow
  3207 00001AD2 723A                <1> 	jc	short dma_bnd_err
  3208                              <1> 	;
  3209                              <1> 	;sub	dx, cx ; 11/07/2022	; Restore start address
  3210                              <1> J33:
  3211                              <1> 	; 08/07/2022
  3212 00001AD4 FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3213 00001AD5 E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LA5T F/F
  3214                              <1> 	IODELAY				; WAIT FOR I/O
  2126 00001AD7 EB00                <2>  jmp short $+2
  2127 00001AD9 EB00                <2>  jmp short $+2
  3215 00001ADB E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3216                              <1> 	;mov	eax, edx		; Buffer address
  3217                              <1> 	; 11/07/2022
  3218 00001ADD 89E8                <1> 	mov	eax, ebp ; buffer address
  3219 00001ADF E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3220                              <1> 	IODELAY				; WAIT FOR I/O
  2126 00001AE1 EB00                <2>  jmp short $+2
  2127 00001AE3 EB00                <2>  jmp short $+2
  3221 00001AE5 88E0                <1> 	mov	al, ah
  3222 00001AE7 E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3223 00001AE9 C1E810              <1> 	shr	eax, 16
  3224                              <1> 	IODELAY				; I/O WAIT STATE
  2126 00001AEC EB00                <2>  jmp short $+2
  2127 00001AEE EB00                <2>  jmp short $+2
  3225 00001AF0 E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3226                              <1> 	IODELAY
  2126 00001AF2 EB00                <2>  jmp short $+2
  2127 00001AF4 EB00                <2>  jmp short $+2
  3227                              <1> 	;mov	ax, cx			; Byte count - 1
  3228 00001AF6 88C8                <1> 	mov	al, cl
  3229 00001AF8 E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3230                              <1> 	IODELAY				; WAIT FOR I/O
  2126 00001AFA EB00                <2>  jmp short $+2
  2127 00001AFC EB00                <2>  jmp short $+2
  3231                              <1> 	;mov	al, ah
  3232 00001AFE 88E8                <1> 	mov	al, ch
  3233 00001B00 E605                <1> 	OUT	DMA+5, al		; HIGH BYTE OF COUNT
  3234                              <1> 	IODELAY
  2126 00001B02 EB00                <2>  jmp short $+2
  2127 00001B04 EB00                <2>  jmp short $+2
  3235 00001B06 FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3236 00001B07 B002                <1> 	mov	al, 2			; MODE FOR 8237
  3237 00001B09 E60A                <1> 	OUT	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3238                              <1> 
  3239 00001B0B F8                  <1> 	clc	; 04/02/2016
  3240 00001B0C C3                  <1> 	retn
  3241                              <1> 
  3242                              <1> dma_bnd_err_stc:
  3243 00001B0D F9                  <1> 	stc
  3244                              <1> dma_bnd_err:
  3245 00001B0E C605[8C630000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3246 00001B15 C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3247                              <1> 
  3248                              <1> ;-------------------------------------------------------------------------------
  3249                              <1> ; NEC_INIT	
  3250                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3251                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3252                              <1> ;
  3253                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3254                              <1> ;
  3255                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3256                              <1> ;-------------------------------------------------------------------------------
  3257                              <1> NEC_INIT:
  3258                              <1> 	; 11/07/2022
  3259                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3260                              <1> 	;push	ax			; SAVE NEC COMMAND
  3261                              <1> 	; 24/12/2021
  3262 00001B16 50                  <1> 	push	eax
  3263 00001B17 E886020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3264                              <1> 
  3265                              <1> ;-----	DO THE SEEK OPERATION
  3266                              <1> 
  3267                              <1> 	;mov	ch, [ebp+1]		; CH = TRACK #
  3268                              <1> 	; 11/07/2022
  3269 00001B1C 89F1                <1> 	mov	ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector
  3270 00001B1E C1E908              <1> 	shr	ecx, 8
  3271                              <1> 	; ch = track #	
  3272                              <1> 
  3273 00001B21 E86B030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3274                              <1> 	;pop	ax			; RECOVER COMMAND
  3275                              <1> 	; 24/12/2021
  3276 00001B26 58                  <1> 	pop	eax
  3277 00001B27 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3278 00001B29 BB[461B0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3279 00001B2E 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3280                              <1> 
  3281                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3282                              <1> 
  3283 00001B2F E824030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3284 00001B34 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3285 00001B36 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3286 00001B38 C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3287 00001B3B 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3288 00001B3E 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3289 00001B40 E813030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3290 00001B45 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3291                              <1> ER_1:
  3292 00001B46 C3                  <1> 	retn
  3293                              <1> 
  3294                              <1> ;-------------------------------------------------------------------------------
  3295                              <1> ; RWV_COM
  3296                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3297                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3298                              <1> ;
  3299                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3300                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3301                              <1> ;-------------------------------------------------------------------------------
  3302                              <1> RWV_COM:
  3303                              <1> 	; 11/07/2022
  3304                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3305 00001B47 B8[941B0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3306 00001B4C 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3307                              <1> 	;mov	ah, [ebp+1]		; OUTPUT TRACK #
  3308                              <1> 	; 11/07/2022
  3309 00001B4D 89F0                <1> 	mov	eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track
  3310 00001B4F C1E808              <1> 	shr	eax, 8
  3311                              <1> 	; ah = track # 
  3312 00001B52 E801030000          <1> 	call	NEC_OUTPUT
  3313 00001B57 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3314                              <1> 	; ah = head #
  3315 00001B59 E8FA020000          <1> 	call	NEC_OUTPUT
  3316                              <1>         ;mov	ah, [ebp]		; OUTPUT SECTOR #
  3317 00001B5E 89F0                <1> 	mov	eax, esi
  3318 00001B60 88C4                <1> 	mov	ah, al
  3319                              <1>  	; ah = sector #
  3320 00001B62 E8F1020000          <1> 	CALL	NEC_OUTPUT
  3321                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3322 00001B67 B003                <1> 	mov	al, 3 ; 08/07/2022
  3323 00001B69 E8F9010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3324 00001B6E E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3325                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3326 00001B73 B004                <1> 	mov	al, 4 ; 08/07/2022
  3327 00001B75 E8ED010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3328 00001B7A E8D9020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3329 00001B7F 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3330                              <1> _R15:
  3331 00001B82 E8D1020000          <1> 	call	NEC_OUTPUT
  3332                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3333 00001B87 B006                <1> 	mov	al, 6 ; 08/07/2022
  3334 00001B89 E8D9010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3335 00001B8E E8C5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3336 00001B93 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3337                              <1> ER_2:
  3338 00001B94 C3                  <1> 	retn
  3339                              <1> 
  3340                              <1> ;-------------------------------------------------------------------------------
  3341                              <1> ; NEC_TERM
  3342                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3343                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3344                              <1> ;
  3345                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3346                              <1> ;-------------------------------------------------------------------------------
  3347                              <1> 
  3348                              <1> NEC_TERM:
  3349                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3350                              <1> 
  3351                              <1> ;-----	LET THE OPERATION HAPPEN
  3352                              <1> 
  3353 00001B95 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3354 00001B96 E8C7030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3355 00001B9B 9C                  <1> 	pushfd	; 24/12/2021
  3356 00001B9C E8F0030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3357 00001BA1 724B                <1> 	jc	short SET_END_POP
  3358 00001BA3 9D                  <1> 	popfd	; 24/12/2021
  3359 00001BA4 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3360                              <1> 
  3361                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3362                              <1> 
  3363 00001BA6 FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3364 00001BA7 BE[8D630000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3365 00001BAC AC                  <1> 	lodsb				; GET ST0
  3366 00001BAD 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3367 00001BAF 7433                <1> 	jz	short SET_END
  3368 00001BB1 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3369 00001BB3 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3370                              <1> 
  3371                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3372                              <1> 
  3373 00001BB5 AC                  <1> 	lodsb				; GET ST1
  3374 00001BB6 D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3375 00001BB8 B404                <1> 	mov	ah, RECORD_NOT_FND
  3376 00001BBA 7222                <1> 	jc	short J19
  3377 00001BBC C0E002              <1> 	sal	al, 2
  3378 00001BBF B410                <1> 	mov	ah, BAD_CRC
  3379 00001BC1 721B                <1> 	jc	short J19
  3380 00001BC3 D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3381 00001BC5 B408                <1> 	mov	ah, BAD_DMA
  3382 00001BC7 7215                <1> 	jc	short J19
  3383 00001BC9 C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3384 00001BCC B404                <1> 	mov	ah, RECORD_NOT_FND
  3385 00001BCE 720E                <1> 	jc	short J19
  3386 00001BD0 D0E0                <1> 	sal	al, 1
  3387 00001BD2 B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3388 00001BD4 7208                <1> 	jc	short J19
  3389 00001BD6 D0E0                <1> 	sal	al, 1			; TEST MISSING ADDRESS MARK
  3390 00001BD8 B402                <1> 	mov	ah, BAD_ADDR_MARK
  3391 00001BDA 7202                <1> 	jc	short J19
  3392                              <1> 
  3393                              <1> ;----- 	NEC MUST HAVE FAILED
  3394                              <1> J18:
  3395 00001BDC B420                <1> 	mov	ah, BAD_NEC
  3396                              <1> J19:
  3397 00001BDE 0825[8C630000]      <1> 	or	[DSKETTE_STATUS], ah
  3398                              <1> SET_END:
  3399 00001BE4 803D[8C630000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3400 00001BEB F5                  <1> 	cmc
  3401 00001BEC 5E                  <1> 	pop	esi
  3402 00001BED C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3403                              <1> 
  3404                              <1> SET_END_POP:
  3405 00001BEE 9D                  <1> 	popfd	; 24/12/2021
  3406 00001BEF EBF3                <1> 	jmp	short SET_END
  3407                              <1> 
  3408                              <1> ;-------------------------------------------------------------------------------
  3409                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3410                              <1> ;-------------------------------------------------------------------------------
  3411                              <1> DSTATE:
  3412                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3413 00001BF1 803D[8C630000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3414 00001BF8 753E                <1> 	jne	short SETBAC		; IF ERROR JUMP
  3415 00001BFA 808F[97630000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3416 00001C01 F687[97630000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3417 00001C08 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3418 00001C0A 8A87[97630000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3419 00001C10 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3420 00001C12 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3421 00001C14 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3422                              <1> 
  3423                              <1> ;----- 	CHECK IF IT IS 1.44M
  3424                              <1> 
  3425 00001C16 E843010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3426                              <1> 	;;20/02/2015
  3427                              <1> 	;;jc	short M_12		; CMOS BAD
  3428 00001C1B 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3429 00001C1D 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3430 00001C1F 7410                <1> 	je	short M_12		; YES
  3431                              <1> M_720:
  3432 00001C21 80A7[97630000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3433 00001C28 808F[97630000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3434 00001C2F EB07                <1> 	jmp	short SETBAC		; BACK
  3435                              <1> M_12:	
  3436 00001C31 808F[97630000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3437                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3438                              <1> SETBAC:
  3439 00001C38 C3                  <1> 	retn
  3440                              <1> 
  3441                              <1> ;-------------------------------------------------------------------------------
  3442                              <1> ; RETRY	
  3443                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3444                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3445                              <1> ;
  3446                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3447                              <1> ;-------------------------------------------------------------------------------
  3448                              <1> RETRY:
  3449                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3450 00001C39 803D[8C630000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3451 00001C40 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3452 00001C42 803D[8C630000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3453 00001C49 743B                <1> 	je	short NO_RETRY
  3454 00001C4B 8AA7[97630000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3455 00001C51 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3456 00001C54 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3457 00001C56 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3458 00001C59 8A2D[94630000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3459 00001C5F C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3460 00001C62 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3461 00001C65 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3462 00001C67 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3463                              <1> 
  3464                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3465                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3466                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3467                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3468                              <1> 
  3469 00001C69 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3470 00001C6C D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3471 00001C6E 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3472 00001C71 80A7[97630000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3473                              <1> 					; RATE, DBL STEP OFF
  3474 00001C78 08A7[97630000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3475 00001C7E C605[8C630000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3476 00001C85 F9                  <1> 	stc				; SET CARRY FOR RETRY
  3477                              <1> NO_RETRY:	; 08/07/2022
  3478 00001C86 C3                  <1> 	retn				; RETRY RETURN
  3479                              <1> 
  3480                              <1> ;NO_RETRY:
  3481                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3482                              <1> 	;RETn				; NO RETRY RETURN
  3483                              <1> 
  3484                              <1> ;-------------------------------------------------------------------------------
  3485                              <1> ; NUM_TRANS
  3486                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3487                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3488                              <1> ;
  3489                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3490                              <1> ;		SI-HI  = HEAD
  3491                              <1> ;		[BP]   = START SECTOR
  3492                              <1> ;
  3493                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3494                              <1> ;-------------------------------------------------------------------------------
  3495                              <1> NUM_TRANS:
  3496                              <1> 	; 11/07/2022
  3497                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3498 00001C87 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3499 00001C89 803D[8C630000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3500                              <1> 	; 24/12/2021
  3501 00001C90 7529                <1> 	jne	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3502                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3503 00001C92 B004                <1> 	mov	al, 4 ; 08/07/2022
  3504 00001C94 E8CE000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3505                              <1> 	;mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3506 00001C99 A0[92630000]        <1> 	mov	al, [NEC_STATUS+5]
  3507 00001C9E 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3508 00001CA0 88CB                <1> 	mov	bl, cl ; 11/07/2022 ; sector #
  3509 00001CA2 3A2D[91630000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3510 00001CA8 750D                <1> 	jne	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3511                              <1> 	; 11/07/2022
  3512                              <1> 	;mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3513                              <1> 	;cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3514                              <1> 	;jz	short SAME_TR		; IF SAME TRACK NO INCREASE
  3515 00001CAA C1E908              <1> 	shr	ecx, 8 ; byte 3 = track # --> byte 2
  3516 00001CAD 3A2D[90630000]      <1> 	cmp	ch, [NEC_STATUS+3]
  3517 00001CB3 7404                <1> 	je	short SAME_TRK		
  3518                              <1> 	; 11/07/2022
  3519                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3520 00001CB5 00E0                <1> 	add	al, ah
  3521                              <1> DIF_HD:
  3522                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3523 00001CB7 00E0                <1> 	add	al, ah
  3524                              <1> SAME_TRK:
  3525                              <1> 	;sub	bl, [ebp]		; SUBTRACT START FROM END
  3526                              <1> 	;mov	al, bl			; TO AL
  3527 00001CB9 28D8                <1> 	sub	al, bl
  3528                              <1> NT_OUT:
  3529 00001CBB C3                  <1> 	retn
  3530                              <1> 
  3531                              <1> ;-------------------------------------------------------------------------------
  3532                              <1> ; SETUP_DBL
  3533                              <1> ;	CHECK DOUBLE STEP.
  3534                              <1> ;
  3535                              <1> ; ON ENTRY :	EDI = DRIVE #
  3536                              <1> ;
  3537                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3538                              <1> ;-------------------------------------------------------------------------------
  3539                              <1> SETUP_DBL:
  3540                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3541 00001CBC 8AA7[97630000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3542 00001CC2 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3543 00001CC5 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3544                              <1> 
  3545                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3546                              <1> 
  3547 00001CC7 C605[89630000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3548 00001CCE E8CF000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3549 00001CD3 B500                <1> 	mov	ch, 0			; LOAD TRACK 0
  3550 00001CD5 E8B7010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3551 00001CDA E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3552 00001CDF 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3553                              <1> 
  3554                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3555                              <1> 
  3556 00001CE1 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3557 00001CE5 F687[97630000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3558 00001CEC 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3559 00001CEE B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3560                              <1> 
  3561                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3562                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3563                              <1> ;	THEN SET DOUBLE STEP ON.
  3564                              <1> 
  3565                              <1> CNT_OK:
  3566 00001CF0 C605[8B630000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3567                              <1> 	; 24/12/2021
  3568 00001CF7 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3569 00001CF8 C605[8C630000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3570 00001CFF 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3571 00001D01 D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3572 00001D03 C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3573                              <1> 	; 24/12/2021
  3574 00001D06 50                  <1> 	push	eax			; SAVE HEAD
  3575 00001D07 E885010000          <1> 	call	SEEK			; SEEK TO TRACK
  3576                              <1> 	; 24/12/2021
  3577 00001D0C 58                  <1> 	pop	eax			; RESTORE HEAD
  3578 00001D0D 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3579 00001D0F E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3580 00001D14 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3581 00001D15 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3582 00001D1A 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3583                              <1> 	; 24/12/2021
  3584 00001D1B 59                  <1> 	pop	ecx			; RESTORE COUNT
  3585 00001D1C 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3586 00001D1E FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3587 00001D20 38CD                <1> 	cmp	ch, cl			; REACHED MAXIMUM YET
  3588 00001D22 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3589                              <1> 
  3590                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3591                              <1> 
  3592                              <1> SD_ERR:	
  3593 00001D24 F9                  <1> 	stc				; SET CARRY FOR ERROR
  3594 00001D25 C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3595                              <1> 
  3596                              <1> DO_CHK:
  3597 00001D26 8A0D[90630000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3598 00001D2C 888F[99630000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3599 00001D32 D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3600 00001D34 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3601 00001D36 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3602 00001D38 808F[97630000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3603                              <1> NO_DBL:
  3604 00001D3F F8                  <1> 	clc				; CLEAR ERROR FLAG
  3605 00001D40 C3                  <1> 	retn
  3606                              <1> 
  3607                              <1> ;-------------------------------------------------------------------------------
  3608                              <1> ; READ_ID
  3609                              <1> ;	READ ID FUNCTION.
  3610                              <1> ;
  3611                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3612                              <1> ;
  3613                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3614                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3615                              <1> ;-------------------------------------------------------------------------------
  3616                              <1> READ_ID:
  3617                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3618 00001D41 B8[5D1D0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3619 00001D46 50                  <1> 	push	eax
  3620 00001D47 B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3621 00001D49 E80A010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3622 00001D4E 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3623 00001D50 88C4                <1> 	mov	ah, al
  3624 00001D52 E801010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3625 00001D57 E839FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3626 00001D5C 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3627                              <1> ER_3:
  3628 00001D5D C3                  <1> 	retn
  3629                              <1> 
  3630                              <1> ;-------------------------------------------------------------------------------
  3631                              <1> ; CMOS_TYPE
  3632                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3633                              <1> ;
  3634                              <1> ; ON ENTRY:	EDI = DRIVE #
  3635                              <1> ;
  3636                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3637                              <1> ;-------------------------------------------------------------------------------
  3638                              <1> 
  3639                              <1> CMOS_TYPE: ; 11/12/2014
  3640                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3641 00001D5E 8A87[2C5E0000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3642 00001D64 20C0                <1> 	and 	al, al ; 18/12/2014
  3643 00001D66 C3                  <1> 	retn
  3644                              <1> 
  3645                              <1> ;-------------------------------------------------------------------------------
  3646                              <1> ; GET_PARM
  3647                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3648                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3649                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3650                              <1> ;	THE PARAMETER IN DL.
  3651                              <1> ;
  3652                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3653                              <1> ;
  3654                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3655                              <1> ;		AL DESTROYED
  3656                              <1> ;-------------------------------------------------------------------------------
  3657                              <1> GET_PARM:
  3658                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3659                              <1> 	;	 ENTRY:
  3660                              <1> 	;	     AL = INDEX
  3661                              <1> 	;	    EDI = DRIVE #
  3662                              <1> 	; 	 RETURN:
  3663                              <1> 	;	     AH = REQUESTED PARAMETER
  3664                              <1> 	;	     AL DESTROYED
  3665                              <1> 	
  3666                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3667                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3668                              <1> 	;push	esi ; 11/07/2022
  3669 00001D67 53                  <1> 	push	ebx			; SAVE EBX	
  3670 00001D68 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3671                              <1>    	; 17/12/2014
  3672                              <1> 	;mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3673                              <1> 	; 11/07/2022
  3674                              <1> 	;cmp	al, ah
  3675                              <1> 	;je	short gpndc
  3676                              <1> 
  3677                              <1> 	; 11/07/2022
  3678 00001D6B 89F8                <1> 	mov	eax, edi
  3679 00001D6D 3A05[215E0000]      <1> 	cmp	al, [pfd] ; is same with previous drive # ?
  3680 00001D73 7423                <1> 	je	short gpndc	
  3681                              <1> 
  3682 00001D75 A2[215E0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3683                              <1> 
  3684 00001D7A 53                  <1> 	push	ebx ; 08/02/2015
  3685                              <1> 	
  3686                              <1> 	;mov	bl, al 
  3687                              <1> 	; 11/12/2014
  3688                              <1> 	;mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3689                              <1> 	; 11/07/2022
  3690 00001D7B 8A87[2C5E0000]      <1> 	mov	al, [edi+fd0_type]	; Drive type (0,1,2,3,4)	
  3691                              <1> 	; 18/12/2014
  3692 00001D81 20C0                <1> 	and	al, al
  3693 00001D83 7507                <1> 	jnz	short gpdtc
  3694 00001D85 BB[0B5E0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3695 00001D8A EB05                <1>         jmp     short gpdpu
  3696                              <1> gpdtc:	
  3697 00001D8C E89BFBFFFF          <1> 	call	DR_TYPE_CHECK
  3698                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3699                              <1> gpdpu:
  3700 00001D91 891D[A85D0000]      <1> 	mov	[DISK_POINTER], ebx
  3701 00001D97 5B                  <1> 	pop	ebx
  3702                              <1> gpndc:
  3703                              <1> 	;mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3704                              <1> 	;mov	ah, [esi+ebx]		; GET THE WORD
  3705                              <1> 	; 11/07/2022
  3706 00001D98 031D[A85D0000]      <1> 	add	ebx, [DISK_POINTER]
  3707 00001D9E 8A23                <1> 	mov	ah, [ebx] 
  3708 00001DA0 5B                  <1> 	pop	ebx			; RESTORE EBX
  3709                              <1> 	;pop	esi ; 11/07/2022
  3710 00001DA1 C3                  <1> 	retn
  3711                              <1> 
  3712                              <1> ;-------------------------------------------------------------------------------
  3713                              <1> ; MOTOR_ON
  3714                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3715                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3716                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3717                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3718                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3719                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3720                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3721                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3722                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3723                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3724                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3725                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3726                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3727                              <1> ;
  3728                              <1> ; ON ENTRY:	EDI = DRIVE #
  3729                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3730                              <1> ;-------------------------------------------------------------------------------
  3731                              <1> MOTOR_ON:
  3732                              <1> 	; 12/07/2022
  3733                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3734 00001DA2 53                  <1> 	push	ebx			; SAVE REG.
  3735 00001DA3 E820000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3736 00001DA8 721C                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3737                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3738                              <1> 	; 08/07/2022
  3739                              <1> 	;call	XLAT_NEW ; 12/07/2022	; TRANSLATE STATE TO PRESENT ARCH,
  3740                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3741                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3742                              <1> M_WAIT:
  3743                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3744 00001DAA B00A                <1> 	mov	al, 10 ; 08/07/2022
  3745 00001DAC E8B6FFFFFF          <1> 	call	GET_PARM
  3746                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3747 00001DB1 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3748                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3749 00001DB4 7302                <1> 	jae	short J13
  3750 00001DB6 B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3751                              <1> 
  3752                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3753                              <1> GP2:	
  3754                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3755                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3756 00001DB8 B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3757 00001DBD E8F1F6FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3758                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3759 00001DC2 FECC                <1> 	dec	ah
  3760 00001DC4 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3761                              <1> MOT_IS_ON:
  3762 00001DC6 5B                  <1> 	pop	ebx			; RESTORE REG.
  3763 00001DC7 C3                  <1> 	retn
  3764                              <1> 
  3765                              <1> ;-------------------------------------------------------------------------------
  3766                              <1> ; TURN_ON
  3767                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3768                              <1> ;
  3769                              <1> ; ON ENTRY:	EDI = DRIVE #
  3770                              <1> ;
  3771                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3772                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3773                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3774                              <1> ;-------------------------------------------------------------------------------
  3775                              <1> TURN_ON:
  3776                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3777 00001DC8 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3778 00001DCA 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3779 00001DCC C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3780 00001DCF FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3781 00001DD0 C605[8B630000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3782 00001DD7 A0[8A630000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3783 00001DDC 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3784 00001DDE B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3785 00001DE0 D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3786                              <1> 
  3787                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3788                              <1> ;  BL = DRIVE SELECT DESIRED
  3789                              <1> ;  AH = MOTOR ON MASK DESIRED
  3790                              <1> 
  3791 00001DE2 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3792 00001DE4 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3793 00001DE6 8425[8A630000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3794 00001DEC 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3795                              <1> 
  3796                              <1> TURN_IT_ON:
  3797 00001DEE 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3798 00001DF0 8A3D[8A630000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3799 00001DF6 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3800 00001DF9 8025[8A630000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3801 00001E00 0825[8A630000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3802 00001E06 A0[8A630000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3803 00001E0B 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3804 00001E0D 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3805 00001E10 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3806 00001E11 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3807 00001E13 C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3808 00001E16 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3809 00001E18 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3810 00001E1C EE                  <1> 	out	dx, al
  3811 00001E1D 38FB                <1> 	cmp	bl, bh			; NEW MOTOR TURNED ON ?
  3812                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3813 00001E1F 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3814 00001E21 F8                  <1> 	clc				; RESET CARRY MEANING WAIT
  3815 00001E22 C3                  <1> 	retn
  3816                              <1> 
  3817                              <1> NO_MOT_WAIT:
  3818 00001E23 FB                  <1> 	sti
  3819                              <1> no_mot_w1: ; 27/02/2015
  3820 00001E24 F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3821                              <1> 	;sti				; INTERRUPTS BACK ON
  3822 00001E25 C3                  <1> 	retn
  3823                              <1> 
  3824                              <1> ;-------------------------------------------------------------------------------
  3825                              <1> ; HD_WAIT
  3826                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3827                              <1> ;
  3828                              <1> ; ON ENTRY:	DI = DRIVE #
  3829                              <1> ;
  3830                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  3831                              <1> ;-------------------------------------------------------------------------------
  3832                              <1> HD_WAIT:
  3833                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3834                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3835 00001E26 B009                <1> 	mov	al, 9	; 08/07/2022
  3836 00001E28 E83AFFFFFF          <1> 	CALL	GET_PARM
  3837 00001E2D 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3838 00001E2F 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3839 00001E31 F605[8A630000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3840                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3841                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3842                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3843 00001E38 741D                <1> 	jz	short HW_DONE
  3844 00001E3A B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3845 00001E3C 8A87[97630000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3846 00001E42 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3847 00001E44 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3848 00001E46 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3849                              <1> ;GP3:
  3850 00001E48 B414                <1> 	mov	ah, HD320_SETTLE		; USE 320/360 HEAD SETTLE
  3851                              <1> ;	jmp	short DO_WAT
  3852                              <1> 
  3853                              <1> ;ISNT_WRITE:
  3854                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3855                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3856                              <1> 
  3857                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3858                              <1> DO_WAT:
  3859                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3860                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3861                              <1> J29:					; 	1 MILLISECOND LOOP
  3862                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3863                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3864                              <1> 	; 08/07/2022
  3865 00001E4A 29C9                <1> 	sub	ecx, ecx
  3866 00001E4C B142                <1> 	mov	cl, 66
  3867 00001E4E E860F6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3868                              <1> 	;dec	al			; DECREMENT THE COUNT
  3869 00001E53 FECC                <1> 	dec	ah
  3870 00001E55 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3871                              <1> HW_DONE:
  3872 00001E57 C3                  <1> 	retn
  3873                              <1> 
  3874                              <1> ;-------------------------------------------------------------------------------
  3875                              <1> ; NEC_OUTPUT
  3876                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3877                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3878                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3879                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3880                              <1> ; 
  3881                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3882                              <1> ;
  3883                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3884                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3885                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3886                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3887                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3888                              <1> ;
  3889                              <1> ;		EAX, ECX, EDX DESTROYED
  3890                              <1> ;-------------------------------------------------------------------------------
  3891                              <1> 
  3892                              <1> ; 09/12/2014 [Erdogan Tan] 
  3893                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3894                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3895                              <1> ;	This read only register facilitates the transfer of data between
  3896                              <1> ;	the system microprocessor and the controller.
  3897                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3898                              <1> ;	  with the system micrprocessor.
  3899                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3900                              <1> ;	  the transfer is to the controller.
  3901                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3902                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3903                              <1> ; Bit 3 - Reserved.
  3904                              <1> ; Bit 2 - Reserved.
  3905                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3906                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3907                              <1> 
  3908                              <1> ; Data Register (3F5h)
  3909                              <1> ; This read/write register passes data, commands and parameters, and provides
  3910                              <1> ; diskette status information.
  3911                              <1>   		
  3912                              <1> NEC_OUTPUT:
  3913                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3914                              <1> 	;push	ebx			; SAVE REG.
  3915 00001E58 BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  3916                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  3917                              <1> 	; 16/12/2014
  3918                              <1> 	; waiting for (max.) 0.5 seconds
  3919                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  3920                              <1> 	;
  3921                              <1> 	; 17/12/2014
  3922                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  3923                              <1> 	;
  3924                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  3925                              <1> 	;		go on.
  3926                              <1> 	;INPUT:
  3927                              <1> 	;	AH=Mask for isolation bits.
  3928                              <1> 	;	AL=pattern to look for.
  3929                              <1> 	;	DX=Port to test for
  3930                              <1> 	;	ECX=Number of memory refresh periods to delay.
  3931                              <1> 	;	     (normally 30 microseconds per period.)
  3932                              <1> 	;
  3933                              <1> 	;WFP_SHORT:  
  3934                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  3935                              <1> 	;
  3936                              <1> 
  3937 00001E5D B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  3938                              <1> ;
  3939                              <1> ;WFPS_OUTER_LP:
  3940                              <1> ;	;
  3941                              <1> ;WFPS_CHECK_PORT:
  3942                              <1> J23:
  3943 00001E62 EC                  <1> 	in	al, dx			; GET STATUS
  3944 00001E63 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  3945 00001E65 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  3946 00001E67 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  3947                              <1> WFPS_HI:
  3948 00001E69 E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  3949 00001E6B A810                <1> 	test	al, 010h		; transition on memory
  3950 00001E6D 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  3951                              <1> WFPS_LO:
  3952 00001E6F E461                <1> 	in	al, PORT_B		; SYS1
  3953 00001E71 A810                <1> 	test	al, 010h
  3954 00001E73 74FA                <1> 	jz	short WFPS_LO
  3955                              <1> 	;loop	short WFPS_CHECK_PORT
  3956 00001E75 E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  3957                              <1> 
  3958                              <1> 	; fail
  3959                              <1> 
  3960                              <1> ;WFPS_TIMEOUT:
  3961                              <1> 
  3962                              <1> ;-----	FALL THRU TO ERROR RETURN
  3963                              <1> 
  3964 00001E77 800D[8C630000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  3965                              <1> 	;pop	ebx			; RESTORE REG.
  3966 00001E7E 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  3967 00001E7F F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  3968 00001E80 C3                  <1> 	retn
  3969                              <1> 
  3970                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  3971                              <1> 
  3972                              <1> J27:	
  3973 00001E81 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  3974 00001E83 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  3975 00001E84 EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  3976                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  3977                              <1> 	; 27/02/2015
  3978 00001E85 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  3979                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  3980 00001E86 29C9                <1> 	sub	ecx, ecx
  3981 00001E88 B103                <1> 	mov	cl, 3 ; 24/12/2021
  3982 00001E8A E824F6FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  3983 00001E8F 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  3984                              <1> 	;pop	ebx			; RESTORE REG
  3985 00001E90 C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  3986                              <1> 
  3987                              <1> ;-------------------------------------------------------------------------------
  3988                              <1> ; SEEK
  3989                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  3990                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  3991                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  3992                              <1> ;
  3993                              <1> ; ON ENTRY:	EDI = DRIVE #
  3994                              <1> ;		CH = TRACK #
  3995                              <1> ;
  3996                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  3997                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3998                              <1> ;-------------------------------------------------------------------------------
  3999                              <1> SEEK:
  4000                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4001 00001E91 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4002 00001E93 B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4003 00001E95 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  4004 00001E97 D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  4005 00001E99 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  4006 00001E9B 8405[89630000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4007 00001EA1 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4008                              <1> 
  4009 00001EA3 0805[89630000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4010 00001EA9 E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4011 00001EAE 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  4012                              <1> 
  4013                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4014                              <1> 
  4015 00001EB0 C605[8C630000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  4016 00001EB7 E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4017 00001EBC 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4018                              <1> 
  4019                              <1> AFT_RECAL:
  4020 00001EBE C687[99630000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  4021 00001EC5 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  4022 00001EC7 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4023                              <1> 
  4024                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4025                              <1> 
  4026 00001EC9 F687[97630000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4027 00001ED0 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4028 00001ED2 D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  4029                              <1> 
  4030 00001ED4 3AAF[99630000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  4031 00001EDA 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  4032                              <1> 
  4033 00001EDC BA[0F1F0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  4034 00001EE1 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4035 00001EE2 88AF[99630000]      <1> 	mov	[DSK_TRK+edi], ch	; SAVE NEW CYLINDER AS PRESENT POSITION
  4036 00001EE8 B40F                <1> 	mov	ah, 0Fh			; SEEK COMMAND TO NEC
  4037 00001EEA E869FFFFFF          <1> 	call	NEC_OUTPUT
  4038 00001EEF 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4039 00001EF1 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  4040 00001EF3 E860FFFFFF          <1> 	call	NEC_OUTPUT
  4041 00001EF8 8AA7[99630000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  4042 00001EFE E855FFFFFF          <1> 	call	NEC_OUTPUT
  4043 00001F03 E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4044                              <1> 
  4045                              <1> ;-----	WAIT FOR HEAD SETTLE
  4046                              <1> 
  4047                              <1> DO_WAIT:
  4048 00001F08 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  4049 00001F09 E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4050 00001F0E 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  4051                              <1> RB:
  4052                              <1> NEC_ERR:
  4053                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4054                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4055 00001F0F C3                  <1> 	retn				; RETURN TO CALLER
  4056                              <1> 
  4057                              <1> ;-------------------------------------------------------------------------------
  4058                              <1> ; RECAL
  4059                              <1> ;	RECALIBRATE DRIVE
  4060                              <1> ;
  4061                              <1> ; ON ENTRY:	EDI = DRIVE #
  4062                              <1> ;
  4063                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4064                              <1> ;-------------------------------------------------------------------------------
  4065                              <1> RECAL:
  4066                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4067                              <1> 	;push	cx
  4068                              <1> 	; 24/12/2021
  4069 00001F10 51                  <1> 	push	ecx
  4070 00001F11 B8[2D1F0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4071 00001F16 50                  <1> 	push	eax
  4072 00001F17 B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4073 00001F19 E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4074 00001F1E 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4075 00001F20 88DC                <1> 	mov	ah, bl
  4076 00001F22 E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4077 00001F27 E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4078 00001F2C 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4079                              <1> RC_BACK:
  4080                              <1> 	;pop	cx
  4081                              <1> 	; 24/12/2021
  4082 00001F2D 59                  <1> 	pop	ecx
  4083 00001F2E C3                  <1> 	RETn
  4084                              <1> 
  4085                              <1> ;-------------------------------------------------------------------------------
  4086                              <1> ; CHK_STAT_2
  4087                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4088                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4089                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4090                              <1> ;
  4091                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4092                              <1> ;-------------------------------------------------------------------------------
  4093                              <1> CHK_STAT_2:
  4094                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4095 00001F2F B8[571F0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4096 00001F34 50                  <1> 	push	eax
  4097 00001F35 E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4098 00001F3A 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4099 00001F3C B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4100 00001F3E E815FFFFFF          <1> 	call	NEC_OUTPUT
  4101 00001F43 E849000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4102 00001F48 720C                <1> 	jc	short J34
  4103 00001F4A A0[8D630000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4104 00001F4F 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4105 00001F51 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4106 00001F53 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4107 00001F55 F8                  <1> 	clc				; GOOD RETURN
  4108                              <1> J34:
  4109 00001F56 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4110                              <1> CS_BACK:
  4111 00001F57 C3                  <1> 	retn
  4112                              <1> J35:
  4113 00001F58 800D[8C630000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4114 00001F5F F9                  <1> 	stc				; ERROR RETURN CODE
  4115 00001F60 EBF4                <1> 	jmp	short J34
  4116                              <1> 
  4117                              <1> ;-------------------------------------------------------------------------------
  4118                              <1> ; WAIT_INT
  4119                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4120                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4121                              <1> ;	IF THE DRIVE IS NOT READY.
  4122                              <1> ;
  4123                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4124                              <1> ;-------------------------------------------------------------------------------
  4125                              <1> 
  4126                              <1> ; 17/12/2014
  4127                              <1> ; 2.5 seconds waiting !
  4128                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4129                              <1> ; amount of time to wait for completion interrupt from NEC.
  4130                              <1> 
  4131                              <1> WAIT_INT:
  4132                              <1> 	; 12/07/2022
  4133                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4134 00001F62 FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4135                              <1> 	; 12/07/2022
  4136                              <1> 	;clc				; CLEAR TIMEOUT INDICATOR
  4137                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4138                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4139                              <1> 
  4140                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4141                              <1> 	;
  4142                              <1> 	;WAIT_FOR_MEM:	
  4143                              <1> 	;	Waits for a bit at a specified memory location pointed
  4144                              <1> 	;	to by ES:[DI] to become set.
  4145                              <1> 	;INPUT:
  4146                              <1> 	;	AH=Mask to test with.
  4147                              <1> 	;	ES:[DI] = memory location to watch.
  4148                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4149                              <1> 	;	     (normally 30 microseconds per period.)
  4150                              <1> 
  4151                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4152                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4153                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4154                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4155                              <1> 	; 27/02/2015
  4156 00001F63 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4157                              <1> WFMS_CHECK_MEM:
  4158 00001F68 F605[89630000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4159 00001F6F 7516                <1>         jnz     short J37
  4160                              <1> WFMS_HI:
  4161 00001F71 E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4162 00001F73 A810                <1> 	test	al, 010h		; transition on memory
  4163 00001F75 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4164                              <1> WFMS_LO:
  4165 00001F77 E461                <1> 	in	al, PORT_B		; SYS1
  4166 00001F79 A810                <1> 	test	al, 010h
  4167 00001F7B 74FA                <1> 	jz	short WFMS_LO
  4168 00001F7D E2E9                <1>         loop	WFMS_CHECK_MEM
  4169                              <1> ;WFMS_OUTER_LP:
  4170                              <1> ;;	or	bl, bl			; check outer counter
  4171                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4172                              <1> ;	dec	bl
  4173                              <1> ;	jz	short J36A	
  4174                              <1> ;	jmp	short WFMS_CHECK_MEM
  4175                              <1> 
  4176                              <1> 	;17/12/2014
  4177                              <1> 	;16/12/2014
  4178                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4179                              <1> ;J36:
  4180                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4181                              <1> ;	jnz	short J37
  4182                              <1> 	;16/12/2014
  4183                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4184                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4185                              <1> 	;jnz	short J36
  4186                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4187                              <1> ;	jb	short J36
  4188                              <1> 
  4189                              <1> ;WFMS_TIMEOUT:
  4190                              <1> ;J36A:
  4191 00001F7F 800D[8C630000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4192 00001F86 F9                  <1> 	stc				; ERROR RETURN
  4193                              <1> J37:
  4194 00001F87 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4195 00001F88 8025[89630000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4196 00001F8F 9D                  <1> 	popf				; RECOVER CARRY
  4197 00001F90 C3                  <1> 	retn				; GOOD RETURN CODE
  4198                              <1> 
  4199                              <1> ;-------------------------------------------------------------------------------
  4200                              <1> ; RESULTS
  4201                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4202                              <1> ;	FOLLOWING AN INTERRUPT.
  4203                              <1> ;
  4204                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4205                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4206                              <1> ;-------------------------------------------------------------------------------
  4207                              <1> RESULTS:
  4208                              <1> 	; 12/07/2022
  4209                              <1> 	; 11/07/2022
  4210                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4211 00001F91 57                  <1> 	push	edi
  4212 00001F92 BF[8D630000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4213 00001F97 B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4214 00001F99 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4215                              <1> 
  4216                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4217                              <1> 
  4218                              <1> _R10: 
  4219                              <1> 	; 16/12/2014
  4220                              <1> 	; wait for (max) 0.5 seconds
  4221                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4222                              <1> 	;xor	cx, cx			; COUNTER
  4223                              <1> 
  4224                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4225                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4226                              <1> 	; 27/02/2015
  4227                              <1> 
  4228 00001F9D B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4229                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4230                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4231                              <1> 
  4232                              <1> WFPSR_OUTER_LP:
  4233                              <1> 	;
  4234                              <1> WFPSR_CHECK_PORT:
  4235                              <1> J39:					; WAIT FOR MASTER
  4236 00001FA2 EC                  <1> 	in	al, dx			; GET STATUS
  4237 00001FA3 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4238 00001FA5 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4239 00001FA7 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4240                              <1> WFPSR_HI:
  4241 00001FA9 E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4242 00001FAB A810                <1> 	test	al, 010h		; transition on memory
  4243 00001FAD 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4244                              <1> WFPSR_LO:
  4245 00001FAF E461                <1> 	in	al, PORT_B		; SYS1
  4246 00001FB1 A810                <1> 	test	al, 010h
  4247 00001FB3 74FA                <1> 	jz	short WFPSR_LO
  4248 00001FB5 E2EB                <1>         loop	WFPSR_CHECK_PORT
  4249                              <1> 	
  4250                              <1> 	;; 27/02/2015
  4251                              <1> 	;;dec	bh
  4252                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4253                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4254                              <1> 
  4255                              <1> 	;;mov	byte [wait_count], 0
  4256                              <1> ;J39:					; WAIT FOR MASTER
  4257                              <1> ;	in	al, dx			; GET STATUS
  4258                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4259                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4260                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4261                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4262                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4263                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4264                              <1> 	;
  4265                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4266                              <1> 	;;jb	short J39	
  4267                              <1> 
  4268                              <1> ;WFPSR_TIMEOUT:
  4269 00001FB7 800D[8C630000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4270 00001FBE F9                  <1> 	stc				; SET ERROR RETURN
  4271 00001FBF EB26                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4272                              <1> 
  4273                              <1> ;-----	READ IN THE STATUS
  4274                              <1> 
  4275                              <1> J42:
  4276 00001FC1 EB00                <1> 	JMP	$+2			; I/O DELAY
  4277                              <1> 	;inc	dx			; POINT AT DATA PORT
  4278 00001FC3 FEC2                <1> 	inc	dl
  4279 00001FC5 EC                  <1> 	in	al, dx			; GET THE DATA
  4280                              <1> 	; 16/12/2014
  4281                              <1> 	NEWIODELAY
  2131 00001FC6 E6EB                <2>  out 0EBh,al
  4282                              <1> 	
  4283                              <1> 	;mov	[edi], al		; STORE THE BYTE
  4284                              <1> 	;inc	edi			; INCREMENT THE POINTER
  4285                              <1> 	; 11/07/2022
  4286 00001FC8 AA                  <1> 	stosb
  4287                              <1> 
  4288                              <1> 	; 16/12/2014
  4289                              <1> ;	push	cx
  4290                              <1> ;	mov	cx, 30
  4291                              <1> ;wdw2:
  4292                              <1> ;	NEWIODELAY
  4293                              <1> ;	loop	wdw2
  4294                              <1> ;	pop	cx
  4295                              <1> 
  4296                              <1> 	;mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4297                              <1> 	; 12/07/2022
  4298 00001FC9 29C9                <1> 	sub	ecx, ecx
  4299 00001FCB B103                <1> 	mov	cl, 3
  4300 00001FCD E8E1F4FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4301                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4302 00001FD2 FECA                <1> 	dec	dl
  4303 00001FD4 EC                  <1> 	in	al, dx			; GET STATUS
  4304                              <1> 	; 16/12/2014
  4305                              <1> 	NEWIODELAY
  2131 00001FD5 E6EB                <2>  out 0EBh,al
  4306                              <1> 	;
  4307 00001FD7 A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4308 00001FD9 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4309                              <1> 
  4310 00001FDB FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4311 00001FDD 75BE                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4312 00001FDF 800D[8C630000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4313 00001FE6 F9                  <1> 	stc				; SET ERROR FLAG
  4314                              <1> 
  4315                              <1> ;-----	RESULT OPERATION IS DONE
  4316                              <1> POPRES:
  4317 00001FE7 5F                  <1> 	pop	edi
  4318 00001FE8 C3                  <1> 	retn				; RETURN WITH CARRY SET
  4319                              <1> 
  4320                              <1> ;-------------------------------------------------------------------------------
  4321                              <1> ; READ_DSKCHNG
  4322                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4323                              <1> ;
  4324                              <1> ; ON ENTRY:	EDI = DRIVE #
  4325                              <1> ;
  4326                              <1> ; ON EXIT:	EDI = DRIVE #
  4327                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4328                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4329                              <1> ;		EAX, ECX, EDX DESTROYED
  4330                              <1> ;-------------------------------------------------------------------------------
  4331                              <1> READ_DSKCHNG:
  4332                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4333 00001FE9 E8B4FDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4334 00001FEE 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4335 00001FF2 EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4336 00001FF3 A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4337 00001FF5 C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4338                              <1> 
  4339                              <1> fdc_int:  
  4340                              <1> 	  ; 30/07/2015	
  4341                              <1> 	  ; 16/02/2015
  4342                              <1> ;int_0Eh: ; 11/12/2014
  4343                              <1> 
  4344                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  4345                              <1> ; DISK_INT
  4346                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4347                              <1> ;
  4348                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4349                              <1> ;-------------------------------------------------------------------------------
  4350                              <1> DISK_INT_1:
  4351                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4352                              <1> 	;push	eax			; SAVE WORK REGISTER
  4353                              <1> 	; 24/12/2021
  4354 00001FF6 50                  <1> 	push	eax
  4355 00001FF7 1E                  <1> 	push	ds
  4356 00001FF8 66B81000            <1> 	mov	ax, KDATA
  4357 00001FFC 8ED8                <1> 	mov 	ds, ax
  4358 00001FFE 800D[89630000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4359 00002005 B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4360 00002007 E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4361 00002009 1F                  <1> 	pop	ds
  4362                              <1> 	;pop	ax			; RECOVER REGISTER
  4363                              <1> 	; 24/12/2021
  4364 0000200A 58                  <1> 	pop	eax
  4365 0000200B CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4366                              <1> 
  4367                              <1> ;-------------------------------------------------------------------------------
  4368                              <1> ; DSKETTE_SETUP
  4369                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4370                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4371                              <1> ;-------------------------------------------------------------------------------
  4372                              <1> DSKETTE_SETUP:
  4373                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4374                              <1> 	;push	eax			; SAVE REGISTERS
  4375                              <1> 	;push	ebx
  4376                              <1> 	;push	ecx
  4377 0000200C 52                  <1> 	push	edx
  4378                              <1> 	;push	edi
  4379                              <1> 	; 14/12/2014
  4380                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4381                              <1> 	;
  4382                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4383                              <1> 
  4384 0000200D 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4385 0000200F 29C9                <1> 	sub	ecx, ecx
  4386 00002011 66890D[97630000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4387                              <1> 	; 08/07/2022
  4388                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4389 00002018 800D[94630000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4390 0000201F 880D[89630000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4391 00002025 880D[8B630000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4392 0000202B 880D[8A630000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4393 00002031 880D[8C630000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4394                              <1> 	;
  4395                              <1> 	; 28/02/2015
  4396                              <1> 	;mov	word [cfd], 100h 
  4397 00002037 E87DF8FFFF          <1> 	call	DSK_RESET
  4398 0000203C 5A                  <1> 	pop	edx
  4399 0000203D C3                  <1> 	retn
  4400                              <1> 
  4401                              <1> ;//////////////////////////////////////////////////////
  4402                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4403                              <1> ;
  4404                              <1> 
  4405                              <1> ; 12/07/2022
  4406                              <1> ;int13h: ; 21/02/2015
  4407                              <1> ;	pushfd
  4408                              <1> ;	push 	cs
  4409                              <1> ;	call 	DISK_IO
  4410                              <1> ;	retn
  4411                              <1> 
  4412                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4413                              <1> ;/////////////////////////////////////////////////////////////////////
  4414                              <1> 
  4415                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4416                              <1> ; ((Direct call instead of int 13h simulation))
  4417                              <1> ;
  4418                              <1> ;		Function in AL
  4419                              <1> ;			0 = reset
  4420                              <1> ;			1 = read
  4421                              <1> ;			2 = write
  4422                              <1> ;		Disk drive number in DL
  4423                              <1> ;			0 & 1 = floppy disks	
  4424                              <1> ;			80h .. 83h = hard disks
  4425                              <1> ;		Sector address (LBA) in ECX
  4426                              <1> ;		Buffer address in EBX
  4427                              <1> ;		R/W sector count is (always) 1
  4428                              <1> ;
  4429                              <1> ;		Return:
  4430                              <1> ;			Status in AH (>0 = error code)
  4431                              <1> ;			if CF = 1 -> error code in AH
  4432                              <1> ;			if CF = 0 -> successful
  4433                              <1> ;			AL = undefined
  4434                              <1> ;
  4435                              <1> ;		Modified registers: (only) EAX
  4436                              <1> 
  4437                              <1> ; 10/07/2022
  4438                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4439                              <1> 
  4440                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4441                              <1> ; 23/02/2015
  4442                              <1> ; 21/02/2015 (unix386.s)
  4443                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4444                              <1> ;
  4445                              <1> ; Original Source Code:
  4446                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4447                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4448                              <1> ;
  4449                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4450                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4451                              <1> ;
  4452                              <1> 
  4453                              <1> ;The wait for controller to be not busy is 10 seconds.
  4454                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4455                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4456                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4457                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4458                              <1> 
  4459                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4460                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4461                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4462                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4463                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4464                              <1> 
  4465                              <1> ;The wait for Data request on read and write longs is
  4466                              <1> ;2000 us. (?)
  4467                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4468                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4469                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4470                              <1> 
  4471                              <1> ; Port 61h (PORT_B)
  4472                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4473                              <1> 
  4474                              <1> ; 23/12/2014
  4475                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4476                              <1> 
  4477                              <1> 	; 11/07/2022
  4478                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4479                              <1> 
  4480                              <1> ;--- INT 13H -------------------------------------------------------------------
  4481                              <1> ;									       :
  4482                              <1> ; FIXED DISK I/O INTERFACE						       :
  4483                              <1> ;									       :
  4484                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4485                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4486                              <1> ;									       :
  4487                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4488                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4489                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4490                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4491                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4492                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4493                              <1> ;									       :
  4494                              <1> ;------------------------------------------------------------------------------:
  4495                              <1> ;									       :
  4496                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4497                              <1> ;									       :
  4498                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4499                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY                        :
  4500                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY                       :
  4501                              <1> ;									       :
  4502                              <1> ;------------------------------------------------------------------------------:
  4503                              <1> ;									       :
  4504                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4505                              <1> ;									       :
  4506                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4507                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4508                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4509                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4510                              <1> ;									       :
  4511                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4512                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4513                              <1> ;				 (10 BITS TOTAL)			       :
  4514                              <1> ;									       :
  4515                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4516                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4517                              <1> ;									       :
  4518                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4519                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4520                              <1> ;									       :
  4521                              <1> ;------------------------------------------------------------------------------:
  4522                              <1> ; OUTPUT								       :
  4523                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4524                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4525                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4526                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4527                              <1> ;									       :
  4528                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4529                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4530                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4531                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4532                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4533                              <1> ;		REWRITTEN.						       :
  4534                              <1> ;									       :
  4535                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4536                              <1> ;	   INPUT:							       :
  4537                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4538                              <1> ;	   OUTPUT:							       :
  4539                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4540                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4541                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4542                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4543                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4544                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4545                              <1> ;									       :
  4546                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4547                              <1> ;	INFORMATION.							       :
  4548                              <1> ;									       :
  4549                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4550                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4551                              <1> ;									       :
  4552                              <1> ;-------------------------------------------------------------------------------
  4553                              <1> 
  4554                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4555                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4556                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4557                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4558                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4559                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4560                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4561                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4562                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4563                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4564                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4565                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4566                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4567                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4568                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4569                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4570                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4571                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4572                              <1> 
  4573                              <1> ;--------------------------------------------------------
  4574                              <1> ;							:
  4575                              <1> ; FIXED DISK PARAMETER TABLE				:
  4576                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4577                              <1> ;							:
  4578                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4579                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4580                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4581                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4582                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4583                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4584                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4585                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4586                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4587                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4588                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4589                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4590                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4591                              <1> ;							:
  4592                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4593                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4594                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4595                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4596                              <1> ;							:
  4597                              <1> ;--------------------------------------------------------
  4598                              <1> 
  4599                              <1> ;--------------------------------------------------------
  4600                              <1> ;							:
  4601                              <1> ; HARDWARE SPECIFIC VALUES				:
  4602                              <1> ;							:
  4603                              <1> ;  -  CONTROLLER I/O PORT				:
  4604                              <1> ;							:
  4605                              <1> ;     > WHEN READ FROM: 				:
  4606                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4607                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4608                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4609                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4610                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4611                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4612                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4613                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4614                              <1> ;							:
  4615                              <1> ;     > WHEN WRITTEN TO:				:
  4616                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4617                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4618                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4619                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4620                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4621                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4622                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4623                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4624                              <1> ;							:
  4625                              <1> ;--------------------------------------------------------
  4626                              <1> 
  4627                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4628                              <1> ;HF1_PORT	equ	0170h	
  4629                              <1> ;HF_REG_PORT	EQU	03F6H
  4630                              <1> ;HF1_REG_PORT	equ	0376h
  4631                              <1> 
  4632                              <1> HDC1_BASEPORT	equ	1F0h
  4633                              <1> HDC2_BASEPORT	equ	170h		
  4634                              <1> 
  4635                              <1> align 2
  4636                              <1> 
  4637                              <1> ;-----		STATUS REGISTER
  4638                              <1> 
  4639                              <1> ST_ERROR	EQU	00000001B	;
  4640                              <1> ST_INDEX	EQU	00000010B	;
  4641                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4642                              <1> ST_DRQ		EQU	00001000B	;
  4643                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4644                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4645                              <1> ST_READY	EQU	01000000B	;
  4646                              <1> ST_BUSY 	EQU	10000000B	;
  4647                              <1> 
  4648                              <1> ;-----		ERROR REGISTER
  4649                              <1> 
  4650                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4651                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4652                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4653                              <1> ;		EQU	00001000B	; NOT USED
  4654                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4655                              <1> ;		EQU	00100000B	; NOT USED
  4656                              <1> ERR_DATA_ECC	EQU	01000000B
  4657                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4658                              <1> 
  4659                              <1> 
  4660                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4661                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4662                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4663                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4664                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4665                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4666                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4667                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4668                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4669                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4670                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4671                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4672                              <1> 
  4673                              <1> ;MAX_FILE	EQU	2
  4674                              <1> ;S_MAX_FILE	EQU	2
  4675                              <1> MAX_FILE	equ	4		; 22/12/2014
  4676                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4677                              <1> 
  4678                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4679                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4680                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4681                              <1> 
  4682                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4683                              <1> 
  4684                              <1> ;-----		COMMAND BLOCK REFERENCE
  4685                              <1> 
  4686                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4687                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4688                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4689                              <1> ; 19/12/2014
  4690                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4691                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4692                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4693                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4694                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4695                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4696                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4697                              <1> 
  4698                              <1> align 2
  4699                              <1> 
  4700                              <1> ;----------------------------------------------------------------
  4701                              <1> ; FIXED DISK I/O SETUP						:
  4702                              <1> ;								:
  4703                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4704                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4705                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4706                              <1> ;								:
  4707                              <1> ;----------------------------------------------------------------
  4708                              <1> 
  4709                              <1> 	; 12/07/2022
  4710                              <1> 	; 11/07/2022
  4711                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4712                              <1> 
  4713                              <1> DISK_SETUP:
  4714                              <1> 	;cli
  4715                              <1> 	;;mov	ax, ABS0 			; GET ABSOLUTE SEGMENT
  4716                              <1> 	;xor	ax, ax
  4717                              <1> 	;mov	ds, ax				; SET SEGMENT REGISTER
  4718                              <1> 	;mov	ax, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4719                              <1> 	;mov	[DISK_VECTOR], ax		; INTO INT 40H
  4720                              <1> 	;mov	ax, [ORG_VECTOR+2]
  4721                              <1> 	;mov	[DISK_VECTOR+2], ax
  4722                              <1> 	;mov	word [ORG_VECTOR], DISK_IO	; FIXED DISK HANDLER
  4723                              <1> 	;mov	[ORG_VECTOR+2], cs
  4724                              <1> 	; 1st controller (primary master, slave) - IRQ 14
  4725                              <1> 	;;mov	word [HDISK_INT], HD_INT	; FIXED DISK INTERRUPT
  4726                              <1> 	;mov	word [HDISK_INT1], HD_INT	;
  4727                              <1> 	;;mov	[HDISK_INT+2], cs
  4728                              <1> 	;mov	[HDISK_INT1+2], cs
  4729                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4730                              <1> 	;mov	word [HDISK_INT2], HD1_INT	;
  4731                              <1> 	;mov	[HDISK_INT2+2], cs
  4732                              <1> 	;
  4733                              <1> 	;;mov	word [HF_TBL_VEC], HD0_DPT	; PARM TABLE DRIVE 80
  4734                              <1> 	;;mov	word [HF_TBL_VEC+2], DPT_SEGM
  4735                              <1> 	;;mov	word [HF1_TBL_VEC], HD1_DPT	; PARM TABLE DRIVE 81
  4736                              <1> 	;;mov	word [HF1_TBL_VEC+2], DPT_SEGM
  4737                              <1> 	;push	cs
  4738                              <1> 	;pop	ds
  4739                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4740                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4741 0000203E C705[A0630000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4741 00002046 0900                <1>
  4742                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4743                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4744 00002048 C705[A4630000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4744 00002050 0900                <1>
  4745                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4746                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4747 00002052 C705[A8630000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4747 0000205A 0900                <1>
  4748                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4749                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4750 0000205C C705[AC630000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4750 00002064 0900                <1>
  4751                              <1> 	;
  4752                              <1> 	;;in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  4753                              <1> 	;;;and	al, 0BFh
  4754                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4755                              <1> 	;;;JMP	$+2
  4756                              <1> 	;;IODELAY
  4757                              <1> 	;;out	INTB01, al
  4758                              <1> 	;;IODELAY
  4759                              <1> 	;;in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  4760                              <1> 	;;and	al, 0FBh 		; SECOND CHIP
  4761                              <1> 	;;;JMP	$+2
  4762                              <1> 	;;IODELAY
  4763                              <1> 	;;out	INTA01, al
  4764                              <1> 	;
  4765                              <1> 	;sti
  4766                              <1> 	;;push	ds			; MOVE ABS0 POINTER TO
  4767                              <1> 	;;pop	es			; EXTRA SEGMENT POINTER
  4768                              <1> 	;;;call	DDS			; ESTABLISH DATA SEGMENT
  4769                              <1> 	;;mov	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4770                              <1> 	;;mov	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4771                              <1> 	;;mov	byte [CONTROL_BYTE],0
  4772                              <1> 	;;mov	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4773                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4774                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4775                              <1> 	;mov	si, hd0_type
  4776 00002066 BE[2E5E0000]        <1> 	mov	esi, hd0_type
  4777                              <1> 	;;mov	cx, 4
  4778                              <1> 	;mov	ecx, 4
  4779                              <1> 	; 11/07/2022
  4780 0000206B 29C9                <1> 	sub	ecx, ecx
  4781 0000206D B104                <1> 	mov	cl, 4
  4782                              <1> hde_l:
  4783 0000206F AC                  <1> 	lodsb
  4784 00002070 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4785 00002072 7206                <1> 	jb	short _L4
  4786 00002074 FE05[9C630000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4787                              <1> _L4: ; 26/02/2015
  4788 0000207A E2F3                <1> 	loop	hde_l	
  4789                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4790                              <1> ;L4:
  4791                              <1> 	; 
  4792                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4793                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4794                              <1> 	;;mov 	cl, 3
  4795                              <1> 	;;
  4796                              <1> 	;;mov	dl, 80h			; CHECK THE CONTROLLER
  4797                              <1> ;;hdc_dl:
  4798                              <1> 	;;mov	ah, 14h			; USE CONTROLLER DIAGNOSTIC COMMAND
  4799                              <1> 	;;int	13h			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4800                              <1> 	;;;jc	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4801                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4802                              <1> 	;;jnc	short hdc_reset0
  4803                              <1> 	;;loop	hdc_dl
  4804                              <1> 	;;; 27/12/2014
  4805                              <1> 	;;stc
  4806                              <1> 	;;retn
  4807                              <1> 	;
  4808                              <1> ;;hdc_reset0:
  4809                              <1> 	; 18/01/2015
  4810 0000207C 8A0D[9C630000]      <1> 	mov	cl, [HF_NUM]
  4811 00002082 20C9                <1> 	and	cl, cl
  4812 00002084 740D                <1> 	jz	short POD_DONE
  4813                              <1> 	;
  4814 00002086 B27F                <1> 	mov	dl, 7Fh
  4815                              <1> hdc_reset1:
  4816 00002088 FEC2                <1> 	inc	dl
  4817                              <1> 	;; 31/12/2015
  4818                              <1> 	;;push	dx
  4819                              <1> 	;;push	cx
  4820                              <1> 	;;push	ds
  4821                              <1> 	;;sub	ax, ax
  4822                              <1> 	;;mov	ds, ax
  4823                              <1> 	;;mov	ax, [TIMER_LOW]		; GET START TIMER COUNTS
  4824                              <1> 	;;pop	ds
  4825                              <1> 	;;mov	bx, ax
  4826                              <1> 	;;add	ax, 6*182		; 60 SECONDS* 18.2
  4827                              <1> 	;;mov	cx, ax
  4828                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4829                              <1> 	;;
  4830                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4831                              <1> 	;;call	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4832                              <1> 	;;pop	cx
  4833                              <1> 	;;pop	dx
  4834                              <1> 	;;
  4835                              <1> 	; 18/01/2015
  4836                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4837                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4838                              <1> 	;mov	ah, 5 ; ALTERNATE RESET
  4839                              <1> 	;;int	13h
  4840                              <1> 	;call	int13h
  4841                              <1> 	; 12/07/2022
  4842 0000208A 30C0                <1> 	xor	al, al  ; reset
  4843 0000208C E803000000          <1> 	call	DISK_IO	
  4844                              <1> 	;
  4845 00002091 E2F5                <1> 	loop	hdc_reset1
  4846                              <1> POD_DONE:
  4847 00002093 C3                  <1> 	RETn
  4848                              <1> 
  4849                              <1> ;----------------------------------------
  4850                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4851                              <1> ;----------------------------------------
  4852                              <1> 
  4853                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4854                              <1> ; ((Direct call instead of int 13h simulation))
  4855                              <1> ;
  4856                              <1> ;		Function in AL
  4857                              <1> ;			0 = reset
  4858                              <1> ;			1 = read
  4859                              <1> ;			2 = write
  4860                              <1> ;		Disk drive number in DL
  4861                              <1> ;			0 & 1 = floppy disks	
  4862                              <1> ;			80h .. 83h = hard disks
  4863                              <1> ;		Sector address (LBA) in ECX
  4864                              <1> ;		Buffer address in EBX
  4865                              <1> ;		R/W sector count is (always) 1
  4866                              <1> ;
  4867                              <1> ;		Return:
  4868                              <1> ;			Status in AH (>0 = error code)
  4869                              <1> ;			if CF = 1 -> error code in AH
  4870                              <1> ;			if CF = 0 -> successful
  4871                              <1> ;			AL = undefined
  4872                              <1> ;
  4873                              <1> ;		Modified registers: (only) EAX
  4874                              <1> 	
  4875                              <1> 
  4876                              <1> ; 11/07/2022
  4877                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4878                              <1> 
  4879                              <1> DISK_IO:
  4880                              <1> 	; 11/07/2022
  4881                              <1> 	; save registers
  4882 00002094 57                  <1> 	push	edi			; ANY
  4883 00002095 56                  <1> 	push	esi			; ANY
  4884 00002096 53                  <1> 	push	ebx			; BUFFER ADDRESS
  4885 00002097 51                  <1> 	push	ecx			; SECTOR ADDRESS (LBA)
  4886 00002098 52                  <1> 	push	edx			; DRIVE NUMBER (DL)
  4887                              <1> 
  4888                              <1> 	;cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4889                              <1> 	;;jae	short A1		; YES, HANDLE HERE
  4890                              <1> 	;;;;int	40H			; DISKETTE HANDLER
  4891                              <1> 	;;;call	int40h
  4892                              <1> 	;;jb	DISKETTE_IO_1
  4893                              <1> 	;; 24/12/2021
  4894                              <1> 	;jnb	short A1
  4895                              <1> 	;jmp	DISKETTE_IO_1
  4896                              <1> 
  4897                              <1> 	; 11/07/2022
  4898 00002099 80FA80              <1> 	cmp	dl, 80h
  4899 0000209C 730B                <1> 	jae	short A1
  4900                              <1> 
  4901 0000209E E8B1F6FFFF          <1> 	call	DISKETTE_IO_1
  4902                              <1> 
  4903                              <1> DISK_IO_RTN:
  4904                              <1> 	; restore registers
  4905 000020A3 5A                  <1> 	pop	edx
  4906 000020A4 59                  <1> 	pop	ecx
  4907 000020A5 5B                  <1> 	pop	ebx
  4908 000020A6 5E                  <1> 	pop	esi
  4909 000020A7 5F                  <1> 	pop	edi
  4910 000020A8 C3                  <1> 	retn	
  4911                              <1> 
  4912                              <1> ;RET_2:
  4913                              <1> ;	retf	4			; BACK TO CALLER
  4914                              <1> 
  4915                              <1> A1:
  4916                              <1> 	; 11/07/2022
  4917                              <1> 	;sti				; ENABLE INTERRUPTS
  4918                              <1> 	;cmp	dl, (80h + S_MAX_FILE - 1)
  4919                              <1> 	;ja	short RET_2
  4920                              <1> 	
  4921                              <1> 	; 18/01/2015
  4922                              <1> 	;;or	ah, ah
  4923                              <1> 	;or	al, al ; 11/07/2022 (reset function)
  4924                              <1> 	;jz	short A3 ; 08/07/2022
  4925                              <1> 	
  4926                              <1> 	;;cmp	ah, 5  ; Alternate reset
  4927                              <1> 	;cmp	al, 5  ; 11/07/2022
  4928                              <1> 	;je	short A2
  4929                              <1> 	
  4930                              <1> 	; 11/07/2022 - no need to check
  4931                              <1> 	;		 (only kernel calls diskio functions)
  4932                              <1> 	;;cmp	ah, M1L/4 ; cmp ah, 6
  4933                              <1> 	;jb	short A3
  4934                              <1> 	;; BAD COMMAND
  4935                              <1>         ;mov     byte [DISK_STATUS1], BAD_CMD
  4936                              <1> ;RET_2:
  4937                              <1> 	;retf	4
  4938                              <1> 
  4939                              <1> 	; 11/07/2022
  4940                              <1> 	;stc
  4941                              <1> 	;retn
  4942                              <1> A2:
  4943                              <1> 	;sub	ah, ah	; Reset
  4944                              <1> 	; 11/07/2022
  4945                              <1> 	;sub	al, al
  4946                              <1> A3:
  4947                              <1> 					; SAVE REGISTERS DURING OPERATION
  4948 000020A9 C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  4949                              <1> 	
  4950                              <1> 	; 11/07/2022
  4951                              <1> 	; 08/07/2022
  4952                              <1> 	;push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  4953                              <1> 	;push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  4954                              <1> 	;push	edx
  4955                              <1> 	;push	esi
  4956                              <1> 	;push	edi
  4957                              <1> 	
  4958 000020AD E80D000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  4959                              <1> 
  4960 000020B2 C9                  <1> 	leave	; 11/07/2022
  4961                              <1> 	
  4962 000020B3 8A25[9B630000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  4963 000020B9 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  4964 000020BC F5                  <1> 	cmc				; SUCCESS OR FAILURE
  4965                              <1> 	
  4966                              <1> 	;pop	edi			; RESTORE REGISTERS
  4967                              <1> 	;pop	esi
  4968                              <1>       	;pop	edx
  4969                              <1> 	;pop	ecx
  4970                              <1> 	;pop	ebx
  4971                              <1> 	
  4972                              <1> 	;leave				; ADJUST (ESP) AND RESTORE (EBP)
  4973                              <1> 	
  4974                              <1> 	; 11/07/2022
  4975                              <1> 	;retf	4			; THROW AWAY SAVED FLAGS
  4976                              <1> 
  4977 000020BD EBE4                <1> 	jmp	short DISK_IO_RTN
  4978                              <1> 
  4979                              <1> DISK_IO_CONT:
  4980                              <1> 	; 11/07/2022
  4981                              <1> 	;	INPUT:
  4982                              <1> 	;	    AL = 0 : reset
  4983                              <1> 	;	    AL = 1 : read
  4984                              <1> 	;	    Al = 2 : write
  4985                              <1> 	; 	
  4986                              <1> 	; 10/07/2022
  4987                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4988                              <1> SU0:
  4989 000020BF C605[9B630000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  4990                              <1> 	; 10/07/2022
  4991 000020C6 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  4992                              <1> 
  4993 000020C8 8A1D[9C630000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  4994 000020CE 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  4995                              <1> 					; (get drive number as 0 to 3)
  4996 000020D1 38D3                <1> 	cmp	bl, dl
  4997                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  4998                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  4999                              <1> 	; 24/12/2021
  5000 000020D3 7705                <1> 	ja	short su0_su1
  5001 000020D5 E98D000000          <1> 	jmp	BAD_COMMAND
  5002                              <1> su0_su1:
  5003                              <1>         ;;03/01/2015
  5004 000020DA 29DB                <1> 	sub	ebx, ebx
  5005 000020DC 88D3                <1> 	mov	bl, dl
  5006 000020DE 883D[B0630000]      <1> 	mov	[LBAMode], bh  ; 0
  5007                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  5008                              <1> 	;jz	short su1		; no
  5009                              <1> 	;inc	byte [LBAMode]
  5010                              <1> ;su1:
  5011                              <1> 	; 21/02/2015 (32 bit modification)
  5012                              <1> 	; 04/01/2015
  5013                              <1> 	;push	ax ; ***
  5014                              <1> 	; 24/12/2021
  5015 000020E4 50                  <1> 	push	eax ; *** ; function (in AL) ; 11/07/2022
  5016                              <1> 	; 24/12/2021
  5017 000020E5 52                  <1> 	push	edx ; *
  5018 000020E6 50                  <1> 	push	eax ; function (in AL)	; 11/07/2022
  5019 000020E7 E8BE030000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5020                              <1> 	; 02/02/2015
  5021 000020EC 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  5022 000020F0 66A3[225E0000]      <1> 	mov	[HF_PORT], ax
  5023 000020F6 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  5024 000020FA 668915[245E0000]    <1> 	mov	[HF_REG_PORT], dx
  5025 00002101 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  5026                              <1> 	; 23/02/2015
  5027 00002104 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5028 00002106 7406                <1> 	jz 	short su1
  5029 00002108 FE05[B0630000]      <1> 	inc	byte [LBAMode] ; 1 
  5030                              <1> su1: 	 
  5031 0000210E C0E804              <1> 	shr 	al, 4
  5032 00002111 2401                <1> 	and	al, 1			
  5033 00002113 A2[265E0000]        <1> 	mov	[hf_m_s], al 
  5034                              <1> 	;
  5035                              <1> 	; 03/01/2015
  5036 00002118 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5037                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  5038 0000211B EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  5039                              <1> 					; Control Byte: (= 08h, here)
  5040                              <1> 					; bit 0 - 0
  5041                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5042                              <1> 					; bit 2 - SRST (software RESET)
  5043                              <1> 					; bit 3 - use extra heads (8 to 15)
  5044                              <1> 					;         -always set to 1-	
  5045                              <1> 					; (bits 3 to 7 are reserved
  5046                              <1> 					;          for ATA devices)
  5047 0000211C 8A25[9D630000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5048 00002122 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  5049 00002125 08C4                <1> 	or	ah, al
  5050 00002127 8825[9D630000]      <1> 	mov	[CONTROL_BYTE], ah	
  5051                              <1> 	; 04/01/2015
  5052                              <1> 	;pop	ax
  5053                              <1> 	; 24/12/2021
  5054 0000212D 58                  <1> 	pop	eax ; function (in AL) ; 11/07/2022
  5055                              <1> 	;pop	dx ; * ;; 14/02/2015
  5056                              <1> 	; 24/12/2021
  5057 0000212E 5A                  <1> 	pop	edx ; *
  5058                              <1> 	;and	ah, ah	; Reset function ?
  5059 0000212F 20C0                <1> 	and	al, al	; 11/07/2022
  5060 00002131 7506                <1> 	jnz	short su2
  5061                              <1> 	;pop	ax ; ***
  5062                              <1> 	; 24/12/2021
  5063 00002133 58                  <1> 	pop	eax ; *** 	
  5064                              <1> 	;;pop	bx
  5065 00002134 E9DE000000          <1>         jmp     DISK_RESET
  5066                              <1> su2:
  5067                              <1> 	; 11/07/2022
  5068                              <1> 	; ecx = sector address (lba)
  5069                              <1> 	;  dl = hard disk drive number (80h, 81h .. 83h)	 
  5070                              <1> 	;  al = function (0 = read, 1 = write)	
  5071                              <1> 
  5072 00002139 803D[B0630000]00    <1> 	cmp	byte [LBAMode], 0
  5073 00002140 7620                <1> 	jna	short su3 ; convert LBA address to CHS parameters
  5074                              <1> 	
  5075                              <1> ;	; 02/02/2015 (LBA read/write function calls)
  5076                              <1> ;	;cmp	ah, 1Bh
  5077                              <1> ;	cmp	ah, 3 ; 08/07/2022
  5078                              <1> ;	jb	short lbarw1
  5079                              <1> ;	;;cmp	ah, 1Ch
  5080                              <1> ;	;cmp	ah, 4 ; 08/07/2022 
  5081                              <1> ;	;ja 	short invldfnc
  5082                              <1> ;	;;pop	dx ; * ; 14/02/2015
  5083                              <1> ;	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5084                              <1> 
  5085 00002142 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5086                              <1> 
  5087                              <1> 	; 11/07/2022
  5088                              <1> 	;; 14/02/2015
  5089                              <1> 	;mov	cl, dl ; 14/02/2015
  5090                              <1> 
  5091                              <1> 	;;mov	dx, bx
  5092                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5093                              <1> 	;;mov	bx, di
  5094                              <1> 	;mov	si, di ; Buffer offset
  5095                              <1> 
  5096                              <1> 	; 11/07/2022
  5097                              <1> 	;jmp	short lbarw2
  5098                              <1> 
  5099                              <1> ;lbarw1:
  5100                              <1> ;	; convert CHS to LBA
  5101                              <1> ;	;
  5102                              <1> ;	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5103                              <1> ;	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5104                              <1> ;	;	+ Sector - 1
  5105                              <1> ;	;push	dx ; * ;; 14/02/2015
  5106                              <1> ;	; 24/12/2021
  5107                              <1> ;	push	edx ; *
  5108                              <1> ;	;xor	dh, dh
  5109                              <1> ;	xor	edx, edx
  5110                              <1> ;	mov	dl, [ebx+14]	; sectors per track (logical)
  5111                              <1> ;	;xor	ah, ah
  5112                              <1> ;	xor	eax, eax
  5113                              <1> ;	mov	al, [ebx+2]	; heads (logical) 
  5114                              <1> ;	dec	al
  5115                              <1> ;	;inc	ax		; 0 =  256
  5116                              <1> ;	inc	eax ; 24/12/2021
  5117                              <1> ;	mul 	dx
  5118                              <1> ;		; AX = # of Heads * Sectors/Track
  5119                              <1> ;	mov	dx, cx
  5120                              <1> ;	;and	cx, 3Fh	 ; sector (1 to 63)
  5121                              <1> ;	and	ecx, 3fh
  5122                              <1> ;	xchg	dl, dh
  5123                              <1> ;	shr	dh, 6
  5124                              <1> ;		; DX = cylinder (0 to 1023)
  5125                              <1> ;	;mul 	dx
  5126                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder
  5127                              <1> ;	mul	edx
  5128                              <1> ;	dec	cl  ; sector - 1
  5129                              <1> ;	;add	ax, cx
  5130                              <1> ;	;adc	dx, 0
  5131                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  5132                              <1> ;	add	eax, ecx
  5133                              <1> ;	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5134                              <1> ;	; 24/12/2021
  5135                              <1> ;	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  5136                              <1> ;	;push	dx
  5137                              <1> ;	;push	ax
  5138                              <1> ;	push	eax
  5139                              <1> ;	mov	al, [ebx+14]  ; sectors per track (logical)	
  5140                              <1> ;	mul	ch
  5141                              <1> ;		; AX = Head * Sectors/Track
  5142                              <1> ;	cwd
  5143                              <1> ;	;pop	dx
  5144                              <1> ;	pop	edx
  5145                              <1> ;	;add	ax, dx
  5146                              <1> ;	;pop	dx
  5147                              <1> ;	;adc	dx, 0 ; add carry bit
  5148                              <1> ;	add	eax, edx
  5149                              <1> ;
  5150                              <1> ;lbarw2:
  5151                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5152                              <1> 	
  5153 00002144 29D2                <1> 	sub	edx, edx ; 21/02/2015
  5154                              <1> 	
  5155                              <1> 	; 11/07/2022
  5156                              <1> 	;mov	dl, cl ; 21/02/2015
  5157                              <1>         
  5158 00002146 C645F800            <1> 	mov     byte [CMD_BLOCK], 0 ; Features Register
  5159                              <1> 				; NOTE: Features register (1F1h, 171h)
  5160                              <1> 				; is not used for ATA device R/W functions. 
  5161                              <1> 				; It is old/obsolete 'write precompensation'
  5162                              <1> 				; register and error register
  5163                              <1> 				; for old ATA/IDE devices.
  5164                              <1> 	; 18/01/2014
  5165                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  5166 0000214A 8A0D[265E0000]      <1> 	mov	cl, [hf_m_s]
  5167                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  5168                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  5169                              <1> 				; bit 6 = 1 = LBA mode
  5170                              <1> 				; bit 7 = 1
  5171 00002150 80C90E              <1> 	or	cl, 0Eh ; 1110b
  5172                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  5173 00002153 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  5174 00002158 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  5175                              <1> 	;or	dh, ch
  5176 0000215B 09C8                <1> 	or	eax, ecx	
  5177                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  5178                              <1> 				  ; (Sector Number Register)
  5179                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  5180                              <1> 				  ; (Cylinder Low Register)
  5181                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  5182                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  5183                              <1> 				  ; (Cylinder High Register)
  5184                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  5185                              <1> 				  ; (Drive/Head Register)
  5186                              <1> 	
  5187                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  5188 0000215D 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  5189                              <1> 	;14/02/2015
  5190                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  5191 00002160 EB3E                <1> 	jmp	short su4
  5192                              <1> su3:
  5193                              <1> 	; 02/02/2015 
  5194                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  5195                              <1> 	;cmp 	ah, 14h
  5196                              <1> 	;jna 	short chsfnc
  5197                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5198                              <1> 	;cmp	ah, 2
  5199                              <1> 	;jna	short chsfnc
  5200                              <1> 	; 11/07/2022 
  5201                              <1> 	; (al = function, read = 1 or write = 2)
  5202 00002162 3C02                <1> 	cmp	al, 2 
  5203 00002164 760B                <1> 	jna	short chsfnc
  5204                              <1> invldfnc:
  5205                              <1>         ; 14/02/2015  
  5206                              <1> 	;pop	es ; **
  5207                              <1>         ;pop	ax ; ***
  5208                              <1>         ; 24/12/2021
  5209 00002166 58                  <1> 	pop	eax ; ***
  5210                              <1> 	;;jmp	short BAD_COMMAND_POP
  5211                              <1> 	; 11/07/2022
  5212                              <1>         ;jmp     short BAD_COMMAND
  5213                              <1> 
  5214                              <1> 	; 11/07/2022
  5215                              <1> BAD_COMMAND:
  5216 00002167 C605[9B630000]01    <1> 	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5217                              <1> 	;mov	al, 0
  5218 0000216E 28C0                <1> 	sub	al, al ; 0
  5219 00002170 C3                  <1> 	retn
  5220                              <1> 
  5221                              <1> chsfnc:	
  5222 00002171 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5223 00002175 66C1E802            <1> 	shr	ax, 2
  5224 00002179 8845F8              <1> 	mov	[CMD_BLOCK], al
  5225                              <1> 	;
  5226                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5227                              <1> 	;;push	edx ; *
  5228                              <1> 	;;mov	dx, [HF_REG_PORT]
  5229                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5230                              <1> 	;;pop	edx ; * 
  5231                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5232                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5233                              <1> 	;;or	ah, al
  5234                              <1> 	;;mov	[CONTROL_BYTE], ah
  5235                              <1> 	;
  5236 0000217C 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5237 0000217E 243F                <1> 	and	al, 3Fh
  5238 00002180 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5239 00002183 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5240 00002186 88C8                <1> 	mov	al, cl
  5241 00002188 C0E806              <1> 	shr	al, 6
  5242 0000218B 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5243                              <1> 	;;05/01/2015
  5244                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5245 0000218E A0[265E0000]        <1> 	mov	al, [hf_m_s]
  5246 00002193 C0E004              <1> 	shl	al, 4
  5247 00002196 80E60F              <1> 	and	dh, 0Fh			; HEAD NUMBER
  5248 00002199 08F0                <1> 	or	al, dh
  5249 0000219B 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5250 0000219D 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5251                              <1> su4:
  5252                              <1> 	;; 14/02/2015
  5253                              <1>         ;;pop	ax
  5254                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5255                              <1>         ;;push	ax
  5256                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5257                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5258                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5259                              <1> 	;pop	ax ; ***
  5260                              <1> 	; 24/12/2021
  5261 000021A0 58                  <1> 	pop	eax ; *** ; function (in AL) ; 11/07/2022
  5262                              <1> 	
  5263                              <1> 	;mov	[CMD_BLOCK+1], al
  5264 000021A1 C645F901            <1>         mov	byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w)
  5265                              <1> 
  5266                              <1> 	; 11/07/2022
  5267                              <1> 	;mov	ebx, esi
  5268                              <1> 	; (esi = buffer address)	
  5269                              <1> 
  5270 000021A5 3C02                <1> 	cmp	al, 2
  5271 000021A7 742D                <1> 	je	short DISK_WRITE
  5272                              <1> 
  5273                              <1> 	;jmp	short DISK_READ
  5274                              <1> 
  5275                              <1> ;	;xor	ebx, ebx
  5276                              <1> ;	;mov	bl, ah
  5277                              <1> ;
  5278                              <1> ;       ;xor	bh, bh
  5279                              <1> ;       ;sal	bx, 1
  5280                              <1> ;       sal	bx, 2	; 32 bit offset (21/02/2015)
  5281                              <1> ;	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5282                              <1> ;       ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5283                              <1> ;       ;;jnb	short BAD_COMMAND_POP
  5284                              <1> ;   	; 08/07/2022
  5285                              <1> ;	;cmp	ebx, M1L
  5286                              <1> ;	;jnb	short BAD_COMMAND
  5287                              <1> ;
  5288                              <1> ;	xchg	ebx, esi
  5289                              <1> ;
  5290                              <1> ;	;;;pop	ax			; RESTORE AX
  5291                              <1> ;	;;;pop	bx			; AND DATA ADDRESS
  5292                              <1> ;	
  5293                              <1> ;	;;push	cx
  5294                              <1> ;	;;push	ax			; ADJUST ES:BX
  5295                              <1> ;	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5296                              <1> ;	;shr	cx, 4
  5297                              <1> ;	;mov	ax, es
  5298                              <1> ;	;add	ax, cx
  5299                              <1> ;	;mov	es, ax
  5300                              <1> ;	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5301                              <1> ;	;;pop	ax
  5302                              <1> ;	;;pop	cx
  5303                              <1> ;
  5304                              <1> ;	jmp	dword [esi+M1]
  5305                              <1> 
  5306                              <1> ;;BAD_COMMAND_POP:
  5307                              <1> ;;	pop	ax
  5308                              <1> ;;	pop	bx
  5309                              <1> ;
  5310                              <1> ;	; 11/07/2022
  5311                              <1> ;BAD_COMMAND:
  5312                              <1> ;	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5313                              <1> ;	;mov	al, 0
  5314                              <1> ;	sub	al, al ; 0
  5315                              <1> ;	retn
  5316                              <1> 
  5317                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5318                              <1> 
  5319                              <1> ;----------------------------------------
  5320                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5321                              <1> ;----------------------------------------
  5322                              <1> ; 
  5323                              <1> DISK_READ:
  5324 000021A9 C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5325                              <1>         ;jmp	COMMANDI
  5326                              <1> 
  5327                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5328                              <1> 
  5329                              <1> ;----------------------------------------
  5330                              <1> ; COMMANDI				:
  5331                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5332                              <1> ;	NSECTOR RETURNS ZERO		:
  5333                              <1> ;----------------------------------------
  5334                              <1> COMMANDI:
  5335                              <1> 	; 11/07/2022 
  5336                              <1> 	;	(check 64K boundary is not needed)
  5337                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5338                              <1> 	;jc	short CMD_ABORT
  5339                              <1> 	
  5340                              <1> 	;mov	di, bx
  5341                              <1> 	; 11/07/2022
  5342                              <1> 	; (esi = buffer address)
  5343                              <1> 	;mov	edi, ebx ; 21/02/2015
  5344 000021AD 89F7                <1> 	mov	edi, esi ; 11/07/2022	
  5345                              <1> 
  5346 000021AF E8A1010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5347 000021B4 751F                <1> 	jnz	short CMD_ABORT
  5348                              <1> CMD_I1:
  5349 000021B6 E80C020000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5350 000021BB 7518                <1> 	jnz	short TM_OUT		; TIME OUT
  5351                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5352                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5353 000021BD 29C9                <1> 	sub	ecx, ecx
  5354 000021BF FEC5                <1> 	inc	ch
  5355                              <1> 	; ecx = 256
  5356                              <1> 	;mov	dx, HF_PORT
  5357 000021C1 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5358 000021C8 FA                  <1> 	cli
  5359 000021C9 FC                  <1> 	cld
  5360 000021CA F3666D              <1> 	rep	insw			; GET THE SECTOR
  5361 000021CD FB                  <1> 	sti
  5362                              <1> 	
  5363                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5364                              <1> 	;jz	short CMD_I3
  5365                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5366                              <1> 	;jc	short TM_OUT
  5367                              <1> 	;;mov	dx, HF_PORT
  5368                              <1> 	;mov	dx,[HF_PORT]
  5369                              <1> 	;xor	ecx, ecx	
  5370                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5371                              <1> 	;mov	cl, 4
  5372                              <1> ;CMD_I2: 
  5373                              <1> 	;inc	al, dx
  5374                              <1> 	;mov 	[edi], al ; 21/02/2015
  5375                              <1> 	;inc	edi
  5376                              <1> 	;loop	CMD_I2
  5377                              <1> CMD_I3: 
  5378 000021CE E810010000          <1> 	call	CHECK_STATUS
  5379 000021D3 7500                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5380                              <1> 	; 11/07/2022
  5381                              <1> 	; (sector count = 1)
  5382                              <1> 	;dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5383                              <1> 	;jnz	SHORT CMD_I1
  5384                              <1> CMD_ABORT:
  5385                              <1> TM_OUT: 
  5386 000021D5 C3                  <1> 	retn
  5387                              <1> 
  5388                              <1> ;---------------------------------------------------
  5389                              <1> 
  5390                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5391                              <1> 
  5392                              <1> ;----------------------------------------
  5393                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5394                              <1> ;----------------------------------------
  5395                              <1> 
  5396                              <1> DISK_WRITE:
  5397 000021D6 C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5398                              <1>         ;JMP	COMMANDO
  5399                              <1> 
  5400                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5401                              <1> 
  5402                              <1> ;----------------------------------------
  5403                              <1> ; COMMANDO				:
  5404                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5405                              <1> ;	NSECTOR RETURNS ZERO		:
  5406                              <1> ;----------------------------------------
  5407                              <1> COMMANDO:
  5408                              <1> 	; 11/07/2022 
  5409                              <1> 	;	(check 64K boundary is not needed)
  5410                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5411                              <1> 	;jc	short CMD_ABORT
  5412                              <1> CMD_OF:
  5413                              <1> 	; 11/07/2022
  5414                              <1> 	; (esi = ebx = buffer address)
  5415                              <1> 	;mov	esi, ebx ; 21/02/2015
  5416 000021DA E876010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5417 000021DF 75F4                <1> 	jnz	short CMD_ABORT
  5418 000021E1 E838020000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5419 000021E6 72ED                <1> 	jc	short TM_OUT		; TOO LONG
  5420                              <1> CMD_O1:
  5421                              <1> 	; 10/07/2022
  5422                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5423 000021E8 31C9                <1> 	xor	ecx, ecx
  5424 000021EA FEC5                <1> 	inc	ch
  5425                              <1> 	; ecx = 256
  5426 000021EC FA                  <1> 	cli
  5427 000021ED FC                  <1> 	cld
  5428 000021EE F3666F              <1> 	rep	outsw
  5429 000021F1 FB                  <1> 	sti
  5430                              <1> 
  5431                              <1> 	; 10/07/2022
  5432                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5433                              <1> 	;jz	short CMD_O3
  5434                              <1> 	;
  5435                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5436                              <1> 	;jc	short TM_OUT
  5437                              <1> 	;;mov	dx, HF_PORT
  5438                              <1> 	;mov	dx, [HF_PORT]
  5439                              <1> 	;sub	ecx, ecx	
  5440                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5441                              <1> 	;mov	cl, 4
  5442                              <1> ;CMD_O2:
  5443                              <1> 	;;lodsb
  5444                              <1> 	;mov	al, [esi]
  5445                              <1> 	;out	dx, al
  5446                              <1> 	;inc	esi
  5447                              <1> 	;loop	CMD_O2
  5448                              <1> 
  5449                              <1> CMD_O3:
  5450 000021F2 E8D0010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5451 000021F7 75DC                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5452 000021F9 E8E5000000          <1> 	call	CHECK_STATUS
  5453 000021FE 75D5                <1> 	jnz	short CMD_ABORT
  5454                              <1> 
  5455                              <1> 	; 11/07/2022
  5456                              <1> 	; (sector count = 1)
  5457                              <1> 	;test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5458                              <1> 	;jnz	short CMD_O1
  5459                              <1> 	
  5460                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5461 00002200 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5462 00002207 80C202              <1> 	add	dl, 2
  5463                              <1> 	;inc	dl
  5464                              <1> 	;inc	dl
  5465 0000220A EC                  <1> 	in	al, dx			;
  5466 0000220B A8FF                <1> 	test	al, 0FFh 		;
  5467 0000220D 7407                <1> 	jz	short CMD_O4		; COUNT = 0  OK
  5468 0000220F C605[9B630000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5469                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5470                              <1> CMD_O4:
  5471 00002216 C3                  <1> 	retn
  5472                              <1> 
  5473                              <1> ; 10/07/2022
  5474                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5475                              <1> 
  5476                              <1> ;----------------------------------------
  5477                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5478                              <1> ;----------------------------------------
  5479                              <1> 
  5480                              <1> ; 18-1-2015 : one controller reset (not other one)
  5481                              <1> 
  5482                              <1> DISK_RESET:
  5483 00002217 FA                  <1> 	cli
  5484 00002218 E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5485                              <1> 	;JMP	$+2
  5486                              <1> 	IODELAY
  2126 0000221A EB00                <2>  jmp short $+2
  2127 0000221C EB00                <2>  jmp short $+2
  5487                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5488 0000221E 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5489 00002220 E6A1                <1> 	out	INTB01, al
  5490 00002222 FB                  <1> 	sti				; START INTERRUPTS
  5491                              <1> 	; 14/02/2015
  5492                              <1> 	;mov	di, dx
  5493                              <1> 	; 24/12/2021
  5494 00002223 89D7                <1> 	mov	edi, edx	
  5495                              <1> 	; 04/01/2015
  5496                              <1> 	;xor	di,di
  5497                              <1> drst0:
  5498 00002225 B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5499                              <1> 	;mov	dx, HF_REG_PORT
  5500 00002227 668B15[245E0000]    <1> 	mov	dx, [HF_REG_PORT]
  5501 0000222E EE                  <1> 	out	dx, al			; RESET
  5502                              <1> ;	mov	cx, 10			; DELAY COUNT
  5503                              <1> ;DRD:	dec	cx
  5504                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5505                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5506                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5507                              <1> 	; 10/07/2022
  5508 0000222F 29C9                <1> 	sub	ecx, ecx
  5509 00002231 B102                <1> 	mov	cl, 2
  5510 00002233 E87BF2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5511                              <1>                                         ; 40 micro seconds)
  5512 00002238 A0[9D630000]        <1> 	mov	al, [CONTROL_BYTE]
  5513 0000223D 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5514 0000223F EE                  <1> 	out	dx, al			; TURN RESET OFF
  5515 00002240 E8B2010000          <1> 	call	NOT_BUSY
  5516 00002245 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5517 00002247 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5518 0000224E FEC2                <1> 	inc	dl  ; HF_PORT+1
  5519                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5520                              <1>         ;mov	cl, 10
  5521                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5522                              <1> 	; 10/07/2022
  5523                              <1> 	;xor	ecx, ecx
  5524 00002250 B10A                <1> 	mov	cl, 10 
  5525                              <1> drst1:
  5526 00002252 EC                  <1> 	in	al, dx			; GET RESET STATUS
  5527 00002253 3C01                <1> 	cmp	al, 1
  5528                              <1> 	; 04/01/2015
  5529 00002255 740C                <1> 	jz	short drst2
  5530                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5531                              <1>         	; Drive/Head Register - bit 4
  5532                              <1> 	;loop	drst1
  5533                              <1> 	; 10/07/2022
  5534 00002257 FEC9                <1> 	dec	cl
  5535 00002259 75F7                <1> 	jnz	short drst1
  5536                              <1> DRERR:	
  5537 0000225B C605[9B630000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5538 00002262 C3                  <1> 	retn
  5539                              <1> drst2:
  5540                              <1> 	; 14/02/2015
  5541                              <1> 	;mov	dx, di
  5542                              <1> 	; 24/12/2021
  5543 00002263 89FA                <1> 	mov	edx, edi
  5544                              <1> ;drst3:
  5545                              <1> ;	; 05/01/2015
  5546                              <1> ;	shl 	di, 1
  5547                              <1> ;	; 04/01/2015
  5548                              <1> ;	mov	ax, [di+hd_cports]
  5549                              <1> ;	cmp	ax, [HF_REG_PORT]
  5550                              <1> ;	je	short drst4
  5551                              <1> ;	mov	[HF_REG_PORT], ax
  5552                              <1> ;	; 03/01/2015
  5553                              <1> ;	mov	ax, [di+hd_ports]
  5554                              <1> ;       mov     [HF_PORT], ax
  5555                              <1> ;	; 05/01/2014
  5556                              <1> ;	shr	di, 1
  5557                              <1> ;	; 04/01/2015
  5558                              <1> ;	jmp	short drst0	; reset other controller
  5559                              <1> ;drst4:
  5560                              <1> ;	; 05/01/2015
  5561                              <1> ;	shr	di, 1
  5562                              <1> ;	mov	al, [di+hd_dregs]
  5563                              <1> ;	and	al, 10h ; bit 4 only
  5564                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5565                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5566                              <1> 	;
  5567 00002265 A0[265E0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5568 0000226A A801                <1> 	test	al, 1
  5569                              <1> 	;jnz	short drst6
  5570 0000226C 7516                <1>         jnz     short drst4
  5571 0000226E 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5572                              <1> ;drst5:
  5573                              <1> drst3:
  5574 00002272 E813000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5575                              <1> 	;mov	dx, di
  5576 00002277 E8A3000000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5577                              <1> 	; 04/01/2014
  5578                              <1> ;	inc	di
  5579                              <1> ;	mov	dx, di
  5580                              <1> ;	cmp	dl, [HF_NUM]
  5581                              <1> ;	jb	short drst3
  5582                              <1> ;DRE:
  5583 0000227C C605[9B630000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5584 00002283 C3                  <1> 	retn
  5585                              <1> ;drst6:
  5586                              <1> drst4:		; Drive/Head Register - bit 4
  5587 00002284 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5588                              <1>         ;jmp    short drst5
  5589 00002288 EBE8                <1>         jmp     short drst3
  5590                              <1> 
  5591                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5592                              <1> 
  5593                              <1> ;----------------------------------------
  5594                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5595                              <1> ;----------------------------------------
  5596                              <1> 	; 03/01/2015
  5597                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5598                              <1> 	; logical sector per logical track
  5599                              <1> 	; and logical heads - 1 would be set but
  5600                              <1> 	; it is seen as it will be good
  5601                              <1> 	; if physical parameters will be set here
  5602                              <1> 	; because, number of heads <= 16.
  5603                              <1> 	; (logical heads usually more than 16)
  5604                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5605                              <1> 	;	== INT 13h physical parameters
  5606                              <1> 
  5607                              <1> ;INIT_DRV:
  5608                              <1> ;	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5609                              <1> ;	call	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5610                              <1> ;	mov	al, [es:bx+2]		; GET NUMBER OF HEADS
  5611                              <1> ;	dec	al			; CONVERT TO 0-INDEX
  5612                              <1> ;	mov	ah, [CMD_BLOCK+5] 	; GET SDH REGISTER
  5613                              <1> ;	and	ah, 0F0h 		; CHANGE HEAD NUMBER
  5614                              <1> ;	or	ah, al			; TO MAX HEAD
  5615                              <1> ;	mov	[CMD_BLOCK+5], ah
  5616                              <1> ;	mov	al, [es:bx+14]		; MAX SECTOR NUMBER
  5617                              <1> ;	mov	[CMD_BLOCK+1], al
  5618                              <1> ;	sub	ax, ax
  5619                              <1> ;	mov	[CMD_BLOCK+3], al 	; ZERO FLAGS
  5620                              <1> ;	call	COMMAND 		; TELL CONTROLLER
  5621                              <1> ;	jnz	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5622                              <1> ;	call	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5623                              <1> ;	jnz	short INIT_EXIT		; TIME OUT
  5624                              <1> ;	call	CHECK_STATUS
  5625                              <1> ;INIT_EXIT:
  5626                              <1> ;	retn
  5627                              <1> 
  5628                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5629                              <1> 
  5630                              <1> ; 04/01/2015
  5631                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5632                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5633                              <1> INIT_DRV:
  5634                              <1> 	;xor	ah, ah
  5635 0000228A 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5636 0000228C B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5637 0000228E 3825[B0630000]      <1>         cmp     [LBAMode], ah   ; 0
  5638 00002294 7702                <1> 	ja	short idrv0
  5639 00002296 B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5640                              <1> idrv0:
  5641                              <1> 	; DL = drive number (0 based)
  5642 00002298 E80D020000          <1> 	call	GET_VEC
  5643                              <1> 	;push	bx
  5644 0000229D 53                  <1> 	push	ebx ; 21/02/2015
  5645                              <1> 	;add	bx, ax
  5646 0000229E 01C3                <1> 	add	ebx, eax
  5647                              <1> 	;; 05/01/2015
  5648 000022A0 8A25[265E0000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5649                              <1> 	;;and 	ah, 1 
  5650 000022A6 C0E404              <1> 	shl	ah, 4
  5651 000022A9 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5652                              <1> 	;mov	al, [es:bx]
  5653 000022AC 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5654 000022AE FEC8                <1> 	dec	al	 ; last head number 
  5655                              <1> 	;and	al, 0Fh
  5656 000022B0 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5657                              <1> 	;
  5658 000022B2 C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5659 000022B6 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5660                              <1> 	;pop	bx
  5661 000022B9 5B                  <1> 	pop	ebx
  5662 000022BA 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5663 000022BC B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5664 000022BE 803D[B0630000]00    <1> 	cmp	byte [LBAMode], 0
  5665 000022C5 7702                <1> 	ja	short idrv1
  5666 000022C7 B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5667                              <1> idrv1:
  5668                              <1> 	;xor	ah, ah
  5669                              <1> 	;add	bx, ax
  5670 000022C9 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5671                              <1> 	;mov	al, [es:bx]
  5672                              <1> 			; sector number
  5673 000022CB 8A03                <1> 	mov	al, [ebx]
  5674 000022CD 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5675 000022D0 28C0                <1> 	sub	al, al
  5676 000022D2 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5677 000022D5 E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5678 000022DA 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5679 000022DC E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5680 000022E1 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5681                              <1> 	;call	CHECK_STATUS
  5682                              <1> 	;jmp	short CHECK_STATUS
  5683                              <1> ;INIT_EXIT:
  5684                              <1> 	;retn
  5685                              <1> 
  5686                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5687                              <1> 
  5688                              <1> ;----------------------------------------
  5689                              <1> ;	CHECK FIXED DISK STATUS 	:
  5690                              <1> ;----------------------------------------
  5691                              <1> CHECK_STATUS:
  5692 000022E3 E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5693                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5694                              <1> 	; 10/07/2022
  5695 000022E8 7510                <1> 	jnz	short CHECK_S2
  5696 000022EA A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5697 000022EC 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5698 000022EE E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5699                              <1> CHECK_S1:
  5700 000022F3 803D[9B630000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5701                              <1> CHECK_S2:
  5702                              <1> INIT_EXIT:	; 10/07/2022
  5703 000022FA C3                  <1> 	retn
  5704                              <1> 
  5705                              <1> ;----------------------------------------
  5706                              <1> ;	TEST DISK READY      (AH = 10H) :
  5707                              <1> ;----------------------------------------
  5708                              <1> 
  5709                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5710 000022FB E8F7000000          <1> 	call	NOT_BUSY
  5711 00002300 751C                <1> 	jnz	short TR_EX
  5712 00002302 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5713 00002305 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5714 0000230C 80C206              <1> 	add	dl,6
  5715 0000230F EE                  <1> 	out	dx, al
  5716 00002310 E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5717 00002315 7507                <1> 	jnz	short TR_EX
  5718 00002317 C605[9B630000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5719                              <1> TR_EX:	
  5720 0000231E C3                  <1> 	retn
  5721                              <1> 
  5722                              <1> ;----------------------------------------
  5723                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5724                              <1> ;----------------------------------------
  5725                              <1> 
  5726                              <1> HDISK_RECAL:
  5727 0000231F C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5728 00002323 E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5729 00002328 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5730 0000232A E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5731 0000232F 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5732 00002331 E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5733 00002336 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5734                              <1> RECAL_X:
  5735 00002338 E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5736 0000233D 803D[9B630000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5737 00002344 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5738 00002346 C605[9B630000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5739                              <1> RECAL_EXIT:
  5740 0000234D 803D[9B630000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5741 00002354 C3                  <1> 	retn
  5742                              <1> 
  5743                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5744                              <1> 
  5745                              <1> ;--------------------------------------------------------
  5746                              <1> ; COMMAND						:
  5747                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5748                              <1> ; OUTPUT						:
  5749                              <1> ;	BL = STATUS					:
  5750                              <1> ;	BH = ERROR REGISTER				:
  5751                              <1> ;--------------------------------------------------------
  5752                              <1> 
  5753                              <1> COMMAND:
  5754                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5755                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5756                              <1> COMMAND1:
  5757                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5758 00002355 E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5759                              <1> 	;;pop	ecx
  5760                              <1> 	;pop	ebx ; 10/07/2022
  5761 0000235A 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5762 0000235C 803D[9B630000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5763                              <1> 	;jz	short CMD_TIMEOUT
  5764                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5765                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5766 00002363 7507                <1> 	jne	short COMMAND4
  5767                              <1> CMD_TIMEOUT:
  5768 00002365 C605[9B630000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5769                              <1> COMMAND4:
  5770                              <1> 	;;pop	ebx ; 10/07/2022
  5771 0000236C 803D[9B630000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5772 00002373 C3                  <1> 	retn
  5773                              <1> COMMAND2:
  5774                              <1> 	;;pop	ebx ; 10/07/2022
  5775                              <1> 	;push	edi ; 10/07/2022
  5776 00002374 C605[96630000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5777 0000237B FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5778 0000237C E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5779                              <1> 	;and	al, 0BFh
  5780 0000237E 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5781                              <1> 	;JMP	$+2
  5782                              <1> 	IODELAY
  2126 00002380 EB00                <2>  jmp short $+2
  2127 00002382 EB00                <2>  jmp short $+2
  5783 00002384 E6A1                <1> 	out	INTB01, al
  5784 00002386 E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5785 00002388 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5786                              <1> 	;JMP	$+2
  5787                              <1> 	IODELAY
  2126 0000238A EB00                <2>  jmp short $+2
  2127 0000238C EB00                <2>  jmp short $+2
  5788 0000238E E621                <1> 	out	INTA01, al
  5789 00002390 FB                  <1> 	sti
  5790                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5791                              <1> 	; 10/07/2022
  5792 00002391 31C9                <1> 	xor	ecx, ecx
  5793                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5794 00002393 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5795 0000239A FEC2                <1> 	inc	dl
  5796 0000239C F605[9D630000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5797 000023A3 7411                <1> 	jz	short COMMAND3
  5798 000023A5 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5799 000023A8 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5800 000023AA 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5801 000023AC 7208                <1> 	jb	short COMMAND3
  5802 000023AE 3C40                <1> 	cmp	al, 40h
  5803 000023B0 7704                <1> 	ja	short COMMAND3
  5804 000023B2 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5805                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5806                              <1> COMMAND3:
  5807                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5808                              <1> 	; 10/07/2022
  5809 000023B6 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5810 000023BA EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5811                              <1> 	IODELAY
  2126 000023BB EB00                <2>  jmp short $+2
  2127 000023BD EB00                <2>  jmp short $+2
  5812                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5813                              <1> 	; 10/07/2022
  5814 000023BF 41                  <1> 	inc	ecx
  5815                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5816 000023C0 42                  <1> 	inc	edx   ; 10/07/2022	
  5817                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5818                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5819 000023C1 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5820 000023C4 72F0                <1> 	jb	short COMMAND3
  5821                              <1> 	;pop	edi ; 10/07/2022
  5822 000023C6 C3                  <1> 	retn				; ZERO FLAG IS SET
  5823                              <1> 
  5824                              <1> ;CMD_TIMEOUT:
  5825                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5826                              <1> ;COMMAND4:
  5827                              <1> ;	pop	ebx
  5828                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5829                              <1> ;	retn
  5830                              <1> 
  5831                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5832                              <1> 
  5833                              <1> ;----------------------------------------
  5834                              <1> ;	WAIT FOR INTERRUPT		:
  5835                              <1> ;----------------------------------------
  5836                              <1> ;WAIT:
  5837                              <1> _WAIT:
  5838 000023C7 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5839                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5840                              <1> 	;clc
  5841                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5842                              <1> 	;int	15h
  5843                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5844                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5845                              <1> 
  5846                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5847                              <1> 	;; 21/02/2015
  5848                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5849                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5850 000023C8 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5851                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5852                              <1> ;-----	WAIT LOOP
  5853                              <1> 
  5854                              <1> WT1:	
  5855                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5856 000023CD F605[96630000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5857                              <1> 	;loopz	WT1
  5858 000023D4 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5859                              <1> 	;dec	bl
  5860                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5861                              <1> 
  5862                              <1> WT1_hi:
  5863 000023D6 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5864 000023D8 A810                <1> 	test	al, 10h			; transition on memory
  5865 000023DA 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5866                              <1> WT1_lo:
  5867 000023DC E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5868 000023DE A810                <1> 	test	al, 10h			
  5869 000023E0 74FA                <1> 	jz	short WT1_lo
  5870 000023E2 E2E9                <1> 	loop	WT1
  5871                              <1> 	;;or	bl, bl
  5872                              <1> 	;;jz	short WT2	
  5873                              <1> 	;;dec	bl
  5874                              <1> 	;;jmp	short WT1
  5875                              <1> 	;dec	bl
  5876                              <1> 	;jnz	short WT1	
  5877                              <1> WT2:	
  5878                              <1> 	; 10/07/2022
  5879                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5880 000023E4 B080                <1> 	mov	al, TIME_OUT
  5881 000023E6 EB07                <1> 	jmp	short WT4
  5882                              <1> WT3:
  5883                              <1> 	;mov	byte [DISK_STATUS1], 0
  5884                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5885 000023E8 28C0                <1> 	sub	al, al ; 0
  5886 000023EA A2[96630000]        <1> 	mov	byte [HF_INT_FLAG], al
  5887                              <1> WT4:
  5888                              <1> NB2:	
  5889 000023EF A2[9B630000]        <1> 	mov	byte [DISK_STATUS1], al
  5890                              <1> 
  5891                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5892 000023F4 20C0                <1> 	and	al, al
  5893                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5894 000023F6 C3                  <1> 	retn
  5895                              <1> 
  5896                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5897                              <1> 
  5898                              <1> ;----------------------------------------
  5899                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5900                              <1> ;----------------------------------------
  5901                              <1> NOT_BUSY:
  5902 000023F7 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5903                              <1> 	;push	ebx
  5904                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5905 000023F8 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5906 000023FF 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  5907                              <1> 	;mov	bl, DELAY_1
  5908                              <1> 					; wait for 10 seconds
  5909                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  5910                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  5911                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  5912 00002402 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  5913                              <1> 	;
  5914                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  5915                              <1> NB1:	
  5916 00002407 EC                  <1> 	in	al, dx			; CHECK STATUS
  5917                              <1> 	;test	al, ST_BUSY
  5918 00002408 2480                <1> 	and	al, ST_BUSY
  5919                              <1> 	;loopnz NB1
  5920 0000240A 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  5921                              <1> 	;dec	bl			
  5922                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  5923                              <1> 
  5924                              <1> NB1_hi: 
  5925 0000240C E461                <1> 	in	al, SYS1		; wait for hi to lo
  5926 0000240E A810                <1> 	test	al, 010h		; transition on memory
  5927 00002410 75FA                <1> 	jnz	short NB1_hi		; refresh.
  5928                              <1> NB1_lo: 
  5929 00002412 E461                <1> 	in	al, SYS1
  5930 00002414 A810                <1> 	test	al, 010h
  5931 00002416 74FA                <1> 	jz	short NB1_lo
  5932 00002418 E2ED                <1> 	loop	NB1
  5933                              <1> 	;dec	bl
  5934                              <1> 	;jnz	short NB1
  5935                              <1> 	;
  5936                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  5937                              <1> 	;;jb	short NB1
  5938                              <1> 	;
  5939                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5940                              <1> 	;jmp	short NB3
  5941 0000241A B080                <1> 	mov	al, TIME_OUT
  5942                              <1> ;NB2:	
  5943 0000241C EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  5944                              <1> 
  5945                              <1> ;	;mov	byte [DISK_STATUS1], 0
  5946                              <1> ;;NB3:	
  5947                              <1> ;	;pop	ebx
  5948                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  5949                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5950                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  5951                              <1> ;	retn
  5952                              <1> 
  5953                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5954                              <1> 
  5955                              <1> ;----------------------------------------
  5956                              <1> ;	WAIT FOR DATA REQUEST		:
  5957                              <1> ;----------------------------------------
  5958                              <1> WAIT_DRQ:
  5959                              <1> 	;mov	cx, DELAY_3
  5960                              <1> 	;mov	dx, HF_PORT+7
  5961 0000241E 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  5962 00002425 80C207              <1> 	add	dl, 7
  5963                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  5964                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  5965                              <1> 					; (but it is written as 2000
  5966                              <1> 					; micro seconds in ATORGS.ASM file
  5967                              <1> 					; of Award Bios - 1999, D1A0622)
  5968 00002428 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  5969                              <1> WQ_1:
  5970 0000242D EC                  <1> 	in	al, dx			; GET STATUS
  5971 0000242E A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  5972 00002430 7516                <1> 	jnz	short WQ_OK
  5973                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  5974                              <1> WQ_hi:	
  5975 00002432 E461                <1> 	in	al, SYS1		; wait for hi to lo
  5976 00002434 A810                <1> 	test	al, 010h		; transition on memory
  5977 00002436 75FA                <1> 	jnz	short WQ_hi		; refresh.
  5978                              <1> WQ_lo:  
  5979 00002438 E461                <1> 	in	al, SYS1
  5980 0000243A A810                <1> 	test	al, 010h
  5981 0000243C 74FA                <1> 	jz	short WQ_lo
  5982 0000243E E2ED                <1> 	loop	WQ_1
  5983                              <1> 
  5984 00002440 C605[9B630000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  5985 00002447 F9                  <1> 	stc
  5986                              <1> WQ_OK:
  5987 00002448 C3                  <1> 	retn
  5988                              <1> ;WQ_OK:
  5989                              <1> 	;clc
  5990                              <1> 	;retn
  5991                              <1> 
  5992                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5993                              <1> 
  5994                              <1> ;----------------------------------------
  5995                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  5996                              <1> ;----------------------------------------
  5997                              <1> CHECK_ST:
  5998                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  5999 00002449 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]
  6000 00002450 80C207              <1> 	add	dl, 7
  6001 00002453 EC                  <1> 	in	al, dx
  6002 00002454 A2[95630000]        <1> 	mov	[HF_STATUS], al
  6003                              <1> 	;mov	ah, 0
  6004 00002459 28E4                <1> 	sub	ah, ah ; 0
  6005 0000245B A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  6006 0000245D 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  6007 0000245F B4CC                <1> 	mov	ah, WRITE_FAULT
  6008 00002461 A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  6009 00002463 7514                <1> 	jnz	short CKST_EXIT
  6010 00002465 B4AA                <1> 	mov	ah, NOT_RDY
  6011 00002467 A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  6012 00002469 740E                <1> 	jz	short CKST_EXIT
  6013 0000246B B440                <1> 	mov	ah, BAD_SEEK
  6014 0000246D A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  6015 0000246F 7408                <1> 	jz	short CKST_EXIT
  6016 00002471 B411                <1> 	mov	ah, DATA_CORRECTED
  6017 00002473 A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  6018 00002475 7502                <1> 	jnz	short CKST_EXIT
  6019                              <1> 	;mov	ah, 0
  6020 00002477 30E4                <1> 	xor	ah, ah ; 0
  6021                              <1> CKST_EXIT:
  6022 00002479 8825[9B630000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  6023 0000247F 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  6024 00002482 7402                <1> 	je	short CKST_EX1
  6025                              <1> 	;cmp	ah, 0
  6026 00002484 20E4                <1> 	and	ah, ah
  6027                              <1> CKST_EX1:
  6028 00002486 C3                  <1> 	retn
  6029                              <1> 
  6030                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6031                              <1> 
  6032                              <1> ;----------------------------------------
  6033                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  6034                              <1> ;----------------------------------------
  6035                              <1> CHECK_ER:
  6036                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  6037 00002487 668B15[225E0000]    <1> 	mov	dx, [HF_PORT]		;
  6038 0000248E FEC2                <1> 	inc	dl
  6039 00002490 EC                  <1> 	in	al, dx
  6040                              <1> 	; 10/07/2022
  6041                              <1> 	;mov	[HF_ERROR], al
  6042                              <1> 	;push	ebx	; 21/02/2015
  6043 00002491 29C9                <1> 	sub	ecx, ecx
  6044                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  6045 00002493 B108                <1> 	mov	cl, 8
  6046                              <1> CK1:	
  6047 00002495 D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  6048 00002497 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  6049 00002499 E2FA                <1> 	loop	CK1			; KEEP TRYING
  6050                              <1> CK2:
  6051                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  6052                              <1> 	;add	ebx, ecx		; ERROR CODE
  6053 0000249B 81C1[185E0000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  6054                              <1> 
  6055                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  6056                              <1> 	;;mov	ah, [bx]
  6057                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  6058 000024A1 8A21                <1> 	mov	ah, [ecx]	
  6059                              <1> CKEX:
  6060 000024A3 8825[9B630000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  6061                              <1> 	; 10/07/2022
  6062                              <1> 	;pop	ebx
  6063                              <1> 	;;cmp	ah, 0
  6064                              <1> 	;and	ah, ah
  6065 000024A9 C3                  <1> 	retn
  6066                              <1> 
  6067                              <1> ;--------------------------------------------------------
  6068                              <1> ; CHECK_DMA						:
  6069                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  6070                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  6071                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  6072                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  6073                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  6074                              <1> ;  -ERROR OTHERWISE					:
  6075                              <1> ;--------------------------------------------------------
  6076                              <1> 
  6077                              <1> 	; 11/07/2022
  6078                              <1> 	; (not needed for hard disks and 32 bit OS)
  6079                              <1> 	;
  6080                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6081                              <1> ;CHECK_DMA:
  6082                              <1> ;	;;push	ax			; SAVE REGISTERS
  6083                              <1> ;	;; 24/12/2021
  6084                              <1> ;	;;push	eax
  6085                              <1> ;	;mov	ax, 8000h		; AH = MAX # SECTORS
  6086                              <1> ;					; AL = MAX OFFSET
  6087                              <1> ;	; 10/07/2022
  6088                              <1> ;	;test	byte [CMD_BLOCK+6], ECC_MODE
  6089                              <1> ;	;jz	short CKD1
  6090                              <1> ;	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  6091                              <1> ;CKD1:	
  6092                              <1> ;	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  6093                              <1> ;	;ja	short CKDOK		; IT WILL FIT
  6094                              <1> ;	;jb	short CKDERR		; TOO MANY
  6095                              <1> ;	
  6096                              <1> ;	cmp	byte [CMD_BLOCK+1], 80h
  6097                              <1> ;	jb	short CKDOK
  6098                              <1> ;	ja	short CKDERR
  6099                              <1> ;	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  6100                              <1> ;	;jb	short CKDERR		; ERROR
  6101                              <1> ;CKD2:
  6102                              <1> ;	or	bl, bl
  6103                              <1> ;	jz	short CKDR
  6104                              <1> ;	
  6105                              <1> ;;CKDOK:	
  6106                              <1> ;	;clc				; CLEAR CARRY
  6107                              <1> ;	;;pop	ax
  6108                              <1> ;	;; 24/12/2021
  6109                              <1> ;	;pop	eax
  6110                              <1> ;	;retn				; NORMAL RETURN
  6111                              <1> ;CKDERR: 
  6112                              <1> ;	stc				; INDICATE ERROR
  6113                              <1> ;	mov	byte [DISK_STATUS1], DMA_BOUNDARY
  6114                              <1> ;	;;pop	ax
  6115                              <1> ;	;; 24/12/2021
  6116                              <1> ;	;pop	eax	
  6117                              <1> ;	retn
  6118                              <1> ;
  6119                              <1> ;	; 10/07/2022
  6120                              <1> ;CKDOK:
  6121                              <1> ;	clc
  6122                              <1> ;CKDR:
  6123                              <1> ;	retn
  6124                              <1> 
  6125                              <1> ;----------------------------------------
  6126                              <1> ;	SET UP EBX-> DISK PARMS	        :
  6127                              <1> ;----------------------------------------
  6128                              <1> 					
  6129                              <1> ; INPUT -> DL = 0 based drive number
  6130                              <1> ; OUTPUT -> EBX = disk parameter table address
  6131                              <1> 
  6132                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6133                              <1> 
  6134                              <1> GET_VEC:
  6135                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  6136                              <1> 	;mov	es, ax
  6137                              <1> 	;test	dl, 1
  6138                              <1> 	;jz	short GV_0
  6139                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  6140                              <1> ;	jmp	short GV_EXIT
  6141                              <1> ;GV_0:
  6142                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  6143                              <1> ;
  6144 000024AA 31DB                <1> 	xor	ebx, ebx
  6145 000024AC 88D3                <1> 	mov	bl, dl
  6146                              <1> 	;02/01/2015
  6147                              <1> 	;xor	bh, bh
  6148                              <1> 	;shl	bl, 1			; port address offset
  6149                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  6150                              <1> 	;shl	bl, 1			; dpt pointer offset
  6151 000024AE C0E302              <1> 	shl	bl, 2
  6152                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  6153 000024B1 81C3[A0630000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  6154                              <1> 	;push	word [bx+2]		; dpt segment
  6155                              <1> 	;pop	es
  6156                              <1> 	;mov	bx, [bx]		; dpt offset
  6157 000024B7 8B1B                <1> 	mov	ebx, [ebx]		
  6158                              <1> ;GV_EXIT:
  6159 000024B9 C3                  <1> 	retn
  6160                              <1> 
  6161                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6162                              <1> hdc1_int: ; 21/02/2015
  6163                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  6164                              <1> ;								:
  6165                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6166                              <1> ;								:
  6167                              <1> ;----------------------------------------------------------------
  6168                              <1> 
  6169                              <1> ; 22/12/2014
  6170                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  6171                              <1> ;	 '11/15/85'
  6172                              <1> ; AWARD BIOS 1999 (D1A0622) 
  6173                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  6174                              <1> 
  6175                              <1> ;int_76h:
  6176                              <1> HD_INT:
  6177                              <1> 	;push	ax
  6178                              <1> 	; 24/12/2021
  6179 000024BA 50                  <1> 	push	eax
  6180 000024BB 1E                  <1> 	push	ds
  6181                              <1> 	;CALL	DDS
  6182                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6183 000024BC 66B81000            <1> 	mov	ax, KDATA
  6184 000024C0 8ED8                <1> 	mov 	ds, ax
  6185                              <1> 	;
  6186                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  6187                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  6188 000024C2 C605[96630000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  6189                              <1> 	;
  6190                              <1> 	;push	dx
  6191                              <1> 	; 24/12/2021
  6192 000024C9 52                  <1> 	push	edx
  6193 000024CA 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  6194                              <1> 					; Clear Controller
  6195                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  6196 000024CE EC                  <1> 	in	al, dx			;
  6197                              <1> 	;pop	dx
  6198                              <1> 	; 24/12/2021
  6199 000024CF 5A                  <1> 	pop	edx
  6200                              <1> 	NEWIODELAY
  2131 000024D0 E6EB                <2>  out 0EBh,al
  6201                              <1> 	;
  6202 000024D2 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  6203 000024D4 E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  6204                              <1> 	;JMP	$+2			; WAIT
  6205                              <1> 	NEWIODELAY
  2131 000024D6 E6EB                <2>  out 0EBh,al
  6206 000024D8 E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  6207 000024DA 1F                  <1> 	pop	ds
  6208                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  6209                              <1> 	;mov	ax, 9100h		; DEVICE POST
  6210                              <1> 	;int	15h			; INTERRUPT
  6211                              <1> irq15_iret: ; 25/02/2015
  6212                              <1> 	;pop	ax
  6213                              <1> 	; 24/12/2021
  6214 000024DB 58                  <1> 	pop	eax
  6215 000024DC CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  6216                              <1> 
  6217                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6218                              <1> hdc2_int: ; 21/02/2015
  6219                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  6220                              <1> ;								:
  6221                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6222                              <1> ;								:
  6223                              <1> ;----------------------------------------------------------------
  6224                              <1> 
  6225                              <1> ;int_77h:
  6226                              <1> HD1_INT:
  6227                              <1> 	;push	ax
  6228                              <1> 	; 24/12/2021
  6229 000024DD 50                  <1> 	push	eax
  6230                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  6231                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  6232 000024DE B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  6233 000024E0 E6A0                <1> 	out	0A0h, al
  6234 000024E2 EB00                <1>         jmp short $+2
  6235 000024E4 EB00                <1> 	jmp short $+2
  6236 000024E6 E4A0                <1> 	in	al, 0A0h
  6237 000024E8 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  6238 000024EA 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  6239                              <1> 	;
  6240 000024EC 1E                  <1> 	push	ds
  6241                              <1> 	;CALL	DDS
  6242                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6243 000024ED 66B81000            <1> 	mov	ax, KDATA
  6244 000024F1 8ED8                <1> 	mov 	ds, ax
  6245                              <1> 	;
  6246                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  6247                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  6248 000024F3 800D[96630000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  6249                              <1> 	;
  6250                              <1> 	;push	dx
  6251                              <1> 	; 24/12/2021
  6252 000024FA 52                  <1> 	push	edx
  6253 000024FB 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6254                              <1> 					; Clear Controller (Award BIOS 1999)
  6255 000024FF EBCD                <1> 	jmp	short Clear_IRQ1415
  6256                              <1> 
  6257                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6258                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6259                              <1> 
  6260                              <1> ;////////////////////////////////////////////////////////////////////
  6261                              <1> ;; END OF DISK I/O SYTEM ///
  2046                                  %include 'memory.inc'  ; 09/03/2015
  2047                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2048                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.18) - MEMORY.INC
  2049                              <1> ; Last Modification: 03/02/2022 [ 31/12/2021 (Retro UNIX 386 v1.1) ]
  2050                              <1> ;
  2051                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2052                              <1> 
  2053                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.1 - MEMORY.INC (31/12/2021)
  2054                              <1> 
  2055                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2056                              <1> 
  2057                              <1> ;;04/11/2014 (unix386.s)	
  2058                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2059                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2060                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2061                              <1> ;;
  2062                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2063                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2064                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2065                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2066                              <1> 
  2067                              <1> ; 27/04/2015
  2068                              <1> ; 09/03/2015
  2069                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2070                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2071                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2072                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2073                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2074                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2075                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2076                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2077                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2078                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2079                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2080                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2081                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2082                              <1> SWP_DISK_READ_ERR 	   equ 40
  2083                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2084                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2085                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2086                              <1> SWP_DISK_WRITE_ERR         equ 44
  2087                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2088                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2089                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2090                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2091                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2092                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2093                              <1> 					; (Indicates that the page is not allocated
  2094                              <1> 					; for the process, it is a shared or system
  2095                              <1>                                         ; page, it must not be deallocated!)
  2096                              <1> ; 14/12/2020
  2097                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2098                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2099                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2100                              <1> 				; (Out of memory allocation table)	
  2101                              <1> ;
  2102                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2103                              <1> ;;
  2104                              <1> ;; 10/10/2014
  2105                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2106                              <1> ;;
  2107                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2108                              <1> ;;	(virtual address = physical address)
  2109                              <1> ;; KERNEL PAGE TABLES:
  2110                              <1> ;;	Kernel page directory and all page tables are
  2111                              <1> ;;	on memory as initialized, as equal to physical memory
  2112                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2113                              <1> ;;
  2114                              <1> ;;	what for: User pages may be swapped out, when accessing
  2115                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2116                              <1> ;;	kernel would have to swap it in! But it is also may be
  2117                              <1> ;;	in use by a user process. (In system/kernel mode
  2118                              <1> ;;	kernel can access all memory pages even if they are
  2119                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2120                              <1> ;;	cause conflicts.) 
  2121                              <1> ;;	
  2122                              <1> ;;	As result of these conditions,
  2123                              <1> ;;	all kernel pages must be initialized as equal to 
  2124                              <1> ;;	physical layout for preventing page faults. 
  2125                              <1> ;;	Also, calling "allocate page" procedure after
  2126                              <1> ;;	a page fault can cause another page fault (double fault)
  2127                              <1> ;;	if all kernel page tables would not be initialized.
  2128                              <1> ;;
  2129                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2130                              <1> ;;	memory allocation table. (double word aligned)
  2131                              <1> ;;
  2132                              <1> ;;	[next_page] = first/next free space to be searched
  2133                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2134                              <1> ;;
  2135                              <1> ;;	[last_page] = End of memory (users space), as offset
  2136                              <1> ;;	to memory allocation table. (double word aligned)
  2137                              <1> ;;
  2138                              <1> ;; USER PAGE TABLES:
  2139                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2140                              <1> ;;		'ready only' marked copies of the 
  2141                              <1> ;;		parent process's page table entries (for
  2142                              <1> ;;		same physical memory).
  2143                              <1> ;;		(A page will be copied to a new page after
  2144                              <1> ;;		 if it causes R/W page fault.)
  2145                              <1> ;;
  2146                              <1> ;;	Every user process has own (different)
  2147                              <1> ;;	page directory and page tables.	
  2148                              <1> ;;
  2149                              <1> ;;	Code starts at virtual address 0, always.
  2150                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2151                              <1> ;;	(Programs can be written/developed as simple
  2152                              <1> ;;	 flat memory programs.)
  2153                              <1> ;;
  2154                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2155                              <1> ;;	Memory page will be allocated by kernel only 
  2156                              <1> ;;		(in kernel/system mode only).
  2157                              <1> ;;	* After a
  2158                              <1> ;;	  - 'not present' page fault
  2159                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2160                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2161                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2162                              <1> ;;	  request by running process.
  2163                              <1> ;;	* While creating a process, allocating a new buffer,
  2164                              <1> ;;	  new page tables etc.
  2165                              <1> ;;
  2166                              <1> ;;	At first,
  2167                              <1> ;;	- 'allocate page' procedure will be called;
  2168                              <1> ;,	   if it will return with a valid (>0) physical address
  2169                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2170                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2171                              <1> ;;	- 'allocate page' will be called for allocating page
  2172                              <1> ;;	   directory, page table and running space (data/code).
  2173                              <1> ;;	- every successful 'allocate page' call will decrease
  2174                              <1> ;;	  'free_pages' count (pointer).
  2175                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2176                              <1> ;;	  if 'free_pages' points to a ZERO.
  2177                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2178                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2179                              <1> ;;	  error except errors caused by attribute conflicts.
  2180                              <1> ;;	 (swapper functions)	 
  2181                              <1> ;;					
  2182                              <1> ;;	At second,
  2183                              <1> ;;	- page directory entry will be updated then page table
  2184                              <1> ;;	  entry will be updated.		
  2185                              <1> ;;
  2186                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2187                              <1> ;;	- M.A.T. has a size according to available memory as
  2188                              <1> ;;	  follows:
  2189                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2190                              <1> ;;		  - a bit with value of 0 means allocated page
  2191                              <1> ;;		  - a bit with value of 1 means a free page
  2192                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2193                              <1> ;;	  depending on M.A.T.
  2194                              <1> ;;		(NOTE: Free page count will not be checked
  2195                              <1> ;;		again -on M.A.T.- after initialization. 
  2196                              <1> ;;		Kernel will trust on initial count.)
  2197                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2198                              <1> ;;	  and it will be increased by deallocation procedures.
  2199                              <1> ;;	
  2200                              <1> ;;	- Available memory will be calculated during
  2201                              <1> ;;	  the kernel's initialization stage (in real mode).
  2202                              <1> ;;	  Memory allocation table and kernel page tables 
  2203                              <1> ;;	  will be formatted/sized as result of available
  2204                              <1> ;;	  memory calculation before paging is enabled.
  2205                              <1> ;;
  2206                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2207                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2208                              <1> ;;	- Memory allocation for kernel page directory size 
  2209                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2210                              <1> ;;	  for page tables)
  2211                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2212                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2213                              <1> ;;	- User (available) space will be started 
  2214                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2215                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2216                              <1> ;;	  memory allocation table and kernel's page directory
  2217                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2218                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2219                              <1> ;; 	  for buffers.
  2220                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2221                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2222                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2223                              <1> ;;
  2224                              <1> ;; For 1GB Available Memory:
  2225                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2226                              <1> ;;	- Memory allocation for kernel page directory size 
  2227                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2228                              <1> ;;	  for page tables)
  2229                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2230                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2231                              <1> ;;	- User (available) space will be started 
  2232                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2233                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2234                              <1> ;;	  memory allocation table and kernel's page directory
  2235                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2236                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2237                              <1> ;; 	  for buffers.
  2238                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2239                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2240                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2241                              <1> ;;
  2242                              <1> ;;
  2243                              <1> 
  2244                              <1> ;;************************************************************************************
  2245                              <1> ;; 
  2246                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2247                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2248                              <1> 
  2249                              <1> ;; Main factor: "sys fork" system call 
  2250                              <1> ;;	
  2251                              <1> ;; 		FORK
  2252                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2253                              <1> ;;  writable pages ---->|
  2254                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2255                              <1> ;; 
  2256                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2257                              <1> ;; 
  2258                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2259                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2260                              <1> ;;       -while R/W bit is 0-. 
  2261                              <1> ;; 
  2262                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2263                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2264                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2265                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2266                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2267                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2268                              <1> ;; 
  2269                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2270                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2271                              <1> ;;   Parent's PTE attributes are not changed.
  2272                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2273                              <1> ;;    destroy/mix previous fork result).
  2274                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2275                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2276                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2277                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2278                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2279                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2280                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2281                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2282                              <1> ;; 
  2283                              <1> ;; !? WHAT FOR (duplication after duplication):
  2284                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2285                              <1> ;; program/executable code continues from specified location as child process, 
  2286                              <1> ;; returns back previous code location as parent process, every child after 
  2287                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2288                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2289                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2290                              <1> ;; was copied to child's process segment (all of code and data) according to
  2291                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2292                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2293                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2294                              <1> ;; (complete running image of parent process) to the child process; 
  2295                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2296                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2297                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2298                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2299                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2300                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2301                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2302                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2303                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2304                              <1> ;; for sharing same read only pages between parent and child processes.
  2305                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2306                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2307                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2308                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2309                              <1> ;; -deallocation problem-.
  2310                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2311                              <1> ;; 
  2312                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2313                              <1> ;; # Page fault handler will do those:
  2314                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2315                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2316                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2317                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2318                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2319                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2320                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2321                              <1> ;;     to child process.)	
  2322                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2323                              <1> ;; # Page fault handler will do those:
  2324                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2325                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2326                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2327                              <1> ;;     address or not. 
  2328                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2329                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2330                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2331                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2332                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2333                              <1> ;; 
  2334                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2335                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2336                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2337                              <1> ;;       duplication method details, it is not possible multiple child processes
  2338                              <1> ;;       were using same page with duplicated PTEs.
  2339                              <1> ;; 
  2340                              <1> ;;************************************************************************************   
  2341                              <1> 
  2342                              <1> ;; 08/10/2014
  2343                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2344                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2345                              <1> 
  2346                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2347                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2348                              <1> ;; (25/08/2014, Revision: 5057) file 
  2349                              <1> ;; by KolibriOS Team (2004-2012)
  2350                              <1> 
  2351                              <1> allocate_page:
  2352                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2353                              <1> 	; 01/07/2015
  2354                              <1> 	; 05/05/2015
  2355                              <1> 	; 30/04/2015
  2356                              <1> 	; 16/10/2014
  2357                              <1> 	; 08/10/2014
  2358                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2359                              <1> 	;
  2360                              <1> 	; INPUT -> none
  2361                              <1> 	;
  2362                              <1> 	; OUTPUT ->
  2363                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2364                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2365                              <1> 	;
  2366                              <1> 	;	CF = 1 and EAX = 0 
  2367                              <1> 	; 		   if there is not a free page to be allocated	
  2368                              <1> 	;
  2369                              <1> 	; Modified Registers -> none (except EAX)
  2370                              <1> 	;
  2371 00002501 A1[10630000]        <1> 	mov	eax, [free_pages]
  2372 00002506 21C0                <1> 	and	eax, eax
  2373 00002508 7438                <1> 	jz	short out_of_memory
  2374                              <1> 	;
  2375 0000250A 53                  <1> 	push	ebx
  2376 0000250B 51                  <1> 	push	ecx
  2377                              <1> 	;
  2378 0000250C BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2379 00002511 89D9                <1> 	mov	ecx, ebx
  2380                              <1>  				     ; NOTE: 32 (first_page) is initial
  2381                              <1> 				     ; value of [next_page].
  2382                              <1> 				     ; It points to the first available
  2383                              <1> 				     ; page block for users (ring 3) ...	
  2384                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2385                              <1> 				     ; (at the of the first 4 MB)		
  2386 00002513 031D[14630000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2387                              <1> 				 ; next_free_page >> 5
  2388 00002519 030D[18630000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2389                              <1> 				 ; (total_pages - 1) >> 5
  2390                              <1> al_p_scan:
  2391 0000251F 39CB                <1> 	cmp	ebx, ecx
  2392 00002521 770A                <1> 	ja	short al_p_notfound
  2393                              <1> 	;
  2394                              <1> 	; 01/07/2015
  2395                              <1> 	; AMD64 Architecture Programmers Manual
  2396                              <1> 	; Volume 3:
  2397                              <1> 	; General-Purpose and System Instructions
  2398                              <1> 	;
  2399                              <1> 	; BSF - Bit Scan Forward
  2400                              <1> 	;
  2401                              <1> 	;   Searches the value in a register or a memory location
  2402                              <1> 	;   (second operand) for the least-significant set bit. 
  2403                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2404                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2405                              <1> 	;   register (first operand). If the second operand contains 0, 
  2406                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2407                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2408                              <1> 	;   of the searched value
  2409                              <1> 	;
  2410 00002523 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2411                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2412                              <1> 			   ; loads the destination with an index to
  2413                              <1> 			   ; first set bit. (0 -> 31) 
  2414                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2415 00002526 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2416                              <1> 			 ;
  2417                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2418                              <1> 			 ;	  with value of 1 means 
  2419                              <1> 			 ;	  the corresponding page is free 
  2420                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2421 00002528 83C304              <1> 	add	ebx, 4
  2422                              <1> 			 ; We return back for searching next page block
  2423                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2424                              <1> 			 ;	 we always will find at least 1 free page here.
  2425 0000252B EBF2                <1>         jmp     short al_p_scan
  2426                              <1> 	;
  2427                              <1> al_p_notfound:
  2428 0000252D 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2429 00002533 890D[14630000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2430                              <1> 				 ; (deallocate_page procedure will change it)
  2431 00002539 31C0                <1> 	xor	eax, eax
  2432 0000253B A3[10630000]        <1> 	mov	[free_pages], eax ; 0
  2433 00002540 59                  <1> 	pop	ecx
  2434 00002541 5B                  <1> 	pop	ebx
  2435                              <1> 	;
  2436                              <1> ; 24/12/2021
  2437                              <1> ; ('swap_out' procedure call is disabled)
  2438                              <1> 
  2439                              <1> out_of_memory:
  2440                              <1> ;	call	swap_out
  2441                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2442                              <1> ;	;
  2443                              <1> ;	sub 	eax, eax ; 0
  2444 00002542 F9                  <1> 	stc
  2445 00002543 C3                  <1> 	retn
  2446                              <1> 
  2447                              <1> al_p_found:
  2448 00002544 89D9                <1> 	mov	ecx, ebx
  2449 00002546 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2450 0000254C 890D[14630000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2451                              <1> 				 ; address/offset (to the next)
  2452 00002552 FF0D[10630000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2453                              <1> 	;
  2454 00002558 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2455                              <1> 				 ; is copied into the Carry Flag and then cleared
  2456                              <1> 				 ; in the destination.
  2457                              <1> 				 ;
  2458                              <1> 				 ; Reset the bit which is corresponding to the 
  2459                              <1> 				 ; (just) allocated page.
  2460                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2461 0000255B C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2462 0000255E 01C8                <1> 	add	eax, ecx	 ; = page number
  2463 00002560 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2464                              <1> 	; EAX = physical address of memory page
  2465                              <1> 	;
  2466                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2467                              <1> 	;       according to this EAX value...
  2468 00002563 59                  <1> 	pop	ecx
  2469 00002564 5B                  <1> 	pop	ebx
  2470                              <1> al_p_ok:
  2471 00002565 C3                  <1> 	retn
  2472                              <1> 
  2473                              <1> make_page_dir:
  2474                              <1> 	; 18/04/2015
  2475                              <1> 	; 12/04/2015
  2476                              <1> 	; 23/10/2014
  2477                              <1> 	; 16/10/2014
  2478                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2479                              <1> 	;
  2480                              <1> 	; INPUT ->
  2481                              <1> 	;	none
  2482                              <1> 	; OUTPUT ->
  2483                              <1> 	;	(EAX = 0)
  2484                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2485                              <1> 	;	cf = 0 ->
  2486                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2487                              <1> 	;		  process/user.
  2488                              <1> 	;
  2489                              <1> 	; Modified Registers -> EAX
  2490                              <1> 	;
  2491 00002566 E896FFFFFF          <1> 	call	allocate_page
  2492 0000256B 7216                <1> 	jc	short mkpd_error
  2493                              <1> 	;
  2494 0000256D A3[1B670000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2495                              <1> 				  ; (Physical address)
  2496                              <1> clear_page:
  2497                              <1> 	; 18/04/2015
  2498                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2499                              <1> 	;
  2500                              <1> 	; INPUT ->
  2501                              <1> 	;	EAX = physical address of the page
  2502                              <1> 	; OUTPUT ->
  2503                              <1> 	;	all bytes of the page will be cleared
  2504                              <1> 	;
  2505                              <1> 	; Modified Registers -> none
  2506                              <1> 	;
  2507 00002572 57                  <1> 	push	edi
  2508 00002573 51                  <1> 	push	ecx
  2509 00002574 50                  <1> 	push	eax
  2510 00002575 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2511 0000257A 89C7                <1> 	mov	edi, eax
  2512 0000257C 31C0                <1> 	xor	eax, eax
  2513 0000257E F3AB                <1> 	rep	stosd
  2514 00002580 58                  <1> 	pop	eax
  2515 00002581 59                  <1> 	pop	ecx
  2516 00002582 5F                  <1> 	pop	edi
  2517                              <1> mkpd_error:
  2518                              <1> mkpt_error:
  2519 00002583 C3                  <1> 	retn
  2520                              <1> 
  2521                              <1> make_page_table:
  2522                              <1> 	; 23/06/2015
  2523                              <1> 	; 18/04/2015
  2524                              <1> 	; 12/04/2015
  2525                              <1> 	; 16/10/2014
  2526                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2527                              <1> 	;
  2528                              <1> 	; INPUT ->
  2529                              <1> 	;	EBX = virtual (linear) address
  2530                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2531                              <1> 	;	      (higher 20 bits must be ZERO)
  2532                              <1> 	;	      (bit 0 must be 1)	 
  2533                              <1> 	;	u.pgdir = page directory (physical) address
  2534                              <1> 	; OUTPUT ->
  2535                              <1> 	;	EDX = Page directory entry address
  2536                              <1> 	;	EAX = Page table address
  2537                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2538                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2539                              <1> 	;
  2540                              <1> 	; Modified Registers -> EAX, EDX
  2541                              <1> 	;
  2542 00002584 E878FFFFFF          <1> 	call	allocate_page
  2543 00002589 72F8                <1> 	jc	short mkpt_error
  2544 0000258B E811000000          <1> 	call	set_pde	
  2545 00002590 EBE0                <1> 	jmp	short clear_page
  2546                              <1> 
  2547                              <1> make_page:
  2548                              <1> 	; 24/07/2015
  2549                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2550                              <1> 	;
  2551                              <1> 	; INPUT ->
  2552                              <1> 	;	EBX = virtual (linear) address
  2553                              <1> 	;	ECX = page attributes (lower 12 bits)
  2554                              <1> 	;	      (higher 20 bits must be ZERO)
  2555                              <1> 	;	      (bit 0 must be 1)	 
  2556                              <1> 	;	u.pgdir = page directory (physical) address
  2557                              <1> 	; OUTPUT ->
  2558                              <1> 	;	EBX = Virtual address
  2559                              <1> 	;	(EDX = PTE value)
  2560                              <1> 	;	EAX = Physical address
  2561                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2562                              <1> 	;
  2563                              <1> 	; Modified Registers -> EAX, EDX
  2564                              <1> 	;
  2565 00002592 E86AFFFFFF          <1> 	call	allocate_page
  2566 00002597 7207                <1> 	jc	short mkp_err
  2567 00002599 E821000000          <1> 	call	set_pte	
  2568 0000259E 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2569                              <1> mkp_err:
  2570 000025A0 C3                  <1> 	retn
  2571                              <1> 
  2572                              <1> set_pde:	; Set page directory entry (PDE)
  2573                              <1> 	; 20/07/2015
  2574                              <1> 	; 18/04/2015
  2575                              <1> 	; 12/04/2015
  2576                              <1> 	; 23/10/2014
  2577                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2578                              <1> 	;
  2579                              <1> 	; INPUT ->
  2580                              <1> 	;	EAX = physical address
  2581                              <1> 	;	      (use present value if EAX = 0)
  2582                              <1> 	;	EBX = virtual (linear) address
  2583                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2584                              <1> 	;	      (higher 20 bits must be ZERO)
  2585                              <1> 	;	      (bit 0 must be 1)	 
  2586                              <1> 	;	u.pgdir = page directory (physical) address
  2587                              <1> 	; OUTPUT ->
  2588                              <1> 	;	EDX = PDE address
  2589                              <1> 	;	EAX = page table address (physical)
  2590                              <1> 	;	;(CF=1 -> Invalid page address)
  2591                              <1> 	;
  2592                              <1> 	; Modified Registers -> EDX
  2593                              <1> 	;
  2594 000025A1 89DA                <1> 	mov	edx, ebx
  2595 000025A3 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2596 000025A6 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2597 000025A9 0315[1B670000]      <1> 	add	edx, [u.pgdir]
  2598                              <1> 	;
  2599 000025AF 21C0                <1> 	and	eax, eax
  2600 000025B1 7506                <1> 	jnz	short spde_1
  2601                              <1> 	;
  2602 000025B3 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2603                              <1> 	;test	al, 1
  2604                              <1> 	;jz	short spde_2
  2605 000025B5 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2606                              <1> spde_1:
  2607                              <1> 	;and	cx, 0FFFh
  2608 000025B9 8902                <1> 	mov	[edx], eax
  2609 000025BB 66090A              <1> 	or	[edx], cx
  2610 000025BE C3                  <1> 	retn
  2611                              <1> ;spde_2: ; error
  2612                              <1> ;	stc
  2613                              <1> ;	retn
  2614                              <1> 
  2615                              <1> set_pte:	; Set page table entry (PTE)
  2616                              <1> 	; 24/07/2015
  2617                              <1> 	; 20/07/2015
  2618                              <1> 	; 23/06/2015
  2619                              <1> 	; 18/04/2015
  2620                              <1> 	; 12/04/2015
  2621                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2622                              <1> 	;
  2623                              <1> 	; INPUT ->
  2624                              <1> 	;	EAX = physical page address
  2625                              <1> 	;	      (use present value if EAX = 0)
  2626                              <1> 	;	EBX = virtual (linear) address
  2627                              <1> 	;	ECX = page attributes (lower 12 bits)
  2628                              <1> 	;	      (higher 20 bits must be ZERO)
  2629                              <1> 	;	      (bit 0 must be 1)	 
  2630                              <1> 	;	u.pgdir = page directory (physical) address
  2631                              <1> 	; OUTPUT ->
  2632                              <1> 	;	EAX = physical page address
  2633                              <1> 	;	(EDX = PTE value)
  2634                              <1> 	;	EBX = virtual address
  2635                              <1> 	;
  2636                              <1> 	;	CF = 1 -> error
  2637                              <1> 	;
  2638                              <1> 	; Modified Registers -> EAX, EDX
  2639                              <1> 	;
  2640 000025BF 50                  <1> 	push	eax
  2641 000025C0 A1[1B670000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2642 000025C5 E837000000          <1> 	call 	get_pde
  2643                              <1> 		; EDX = PDE address
  2644                              <1> 		; EAX = PDE value
  2645 000025CA 5A                  <1> 	pop	edx ; physical page address
  2646 000025CB 722A                <1> 	jc	short spte_err ; PDE not present
  2647                              <1> 	;
  2648 000025CD 53                  <1> 	push	ebx ; 24/07/2015
  2649 000025CE 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2650                              <1> 			    ; EDX = PT address (physical)	
  2651 000025D2 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2652 000025D5 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2653                              <1> 			 ; clear higher 10 bits (PD bits)
  2654 000025DB C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2655 000025DE 01C3                <1> 	add	ebx, eax
  2656                              <1> 	;
  2657 000025E0 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2658 000025E2 A801                <1> 	test	al, 1
  2659 000025E4 740C                <1> 	jz	short spte_0
  2660 000025E6 09D2                <1> 	or	edx, edx
  2661 000025E8 750F                <1> 	jnz	short spte_1
  2662 000025EA 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2663 000025EE 89C2                <1> 	mov	edx, eax
  2664 000025F0 EB09                <1> 	jmp	short spte_2	
  2665                              <1> spte_0:
  2666                              <1> 	; If this PTE contains a swap (disk) address,
  2667                              <1> 	; it can be updated by using 'swap_in' procedure
  2668                              <1> 	; only!
  2669 000025F2 21C0                <1> 	and	eax, eax
  2670 000025F4 7403                <1> 	jz	short spte_1
  2671                              <1> 	; 24/07/2015
  2672                              <1> 	; swapped page ! (on disk)
  2673 000025F6 5B                  <1> 	pop	ebx
  2674                              <1> spte_err:
  2675 000025F7 F9                  <1> 	stc
  2676 000025F8 C3                  <1> 	retn
  2677                              <1> spte_1: 
  2678 000025F9 89D0                <1> 	mov	eax, edx
  2679                              <1> spte_2:
  2680 000025FB 09CA                <1> 	or	edx, ecx
  2681                              <1> 	; 23/06/2015
  2682 000025FD 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2683                              <1> 	; 24/07/2015
  2684 000025FF 5B                  <1> 	pop	ebx
  2685 00002600 C3                  <1> 	retn
  2686                              <1> 
  2687                              <1> get_pde:	; Get present value of the relevant PDE
  2688                              <1> 	; 20/07/2015
  2689                              <1> 	; 18/04/2015
  2690                              <1> 	; 12/04/2015
  2691                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2692                              <1> 	;
  2693                              <1> 	; INPUT ->
  2694                              <1> 	;	EBX = virtual (linear) address
  2695                              <1> 	;	EAX = page directory (physical) address
  2696                              <1> 	; OUTPUT ->
  2697                              <1> 	;	EDX = Page directory entry address
  2698                              <1> 	;	EAX = Page directory entry value
  2699                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2700                              <1> 	; Modified Registers -> EDX, EAX
  2701                              <1> 	;
  2702 00002601 89DA                <1> 	mov	edx, ebx
  2703 00002603 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2704 00002606 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2705 00002609 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2706 0000260B 8B02                <1> 	mov	eax, [edx]
  2707 0000260D A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2708 0000260F 751F                <1> 	jnz	short gpte_retn
  2709 00002611 F9                  <1> 	stc
  2710                              <1> gpde_retn:	
  2711 00002612 C3                  <1> 	retn
  2712                              <1> 
  2713                              <1> get_pte:
  2714                              <1> 		; Get present value of the relevant PTE
  2715                              <1> 	; 29/07/2015
  2716                              <1> 	; 20/07/2015
  2717                              <1> 	; 18/04/2015
  2718                              <1> 	; 12/04/2015
  2719                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2720                              <1> 	;
  2721                              <1> 	; INPUT ->
  2722                              <1> 	;	EBX = virtual (linear) address
  2723                              <1> 	;	EAX = page directory (physical) address
  2724                              <1> 	; OUTPUT ->
  2725                              <1> 	;	EDX = Page table entry address (if CF=0)
  2726                              <1> 	;	      Page directory entry address (if CF=1)
  2727                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2728                              <1> 	;	EAX = Page table entry value (page address)
  2729                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2730                              <1> 	; Modified Registers -> EAX, EDX
  2731                              <1> 	;
  2732 00002613 E8E9FFFFFF          <1> 	call 	get_pde
  2733 00002618 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2734                              <1> 	;jnc	short gpte_1
  2735                              <1> 	;retn
  2736                              <1> ;gpte_1:
  2737 0000261A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2738 0000261E 89DA                <1> 	mov	edx, ebx
  2739 00002620 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2740 00002623 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2741                              <1> 			 ; clear higher 10 bits (PD bits)
  2742 00002629 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2743 0000262C 01C2                <1> 	add	edx, eax
  2744 0000262E 8B02                <1> 	mov	eax, [edx]
  2745                              <1> gpte_retn:
  2746 00002630 C3                  <1> 	retn
  2747                              <1> 
  2748                              <1> deallocate_page_dir:
  2749                              <1> 	; 15/09/2015
  2750                              <1> 	; 05/08/2015
  2751                              <1> 	; 30/04/2015
  2752                              <1> 	; 28/04/2015
  2753                              <1> 	; 17/10/2014
  2754                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2755                              <1> 	;
  2756                              <1> 	; INPUT ->
  2757                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2758                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2759                              <1> 	; OUTPUT ->
  2760                              <1> 	;	All of page tables in the page directory
  2761                              <1> 	;	and page dir's itself will be deallocated
  2762                              <1> 	;	except 'read only' duplicated pages (will be converted
  2763                              <1> 	;	to writable pages).
  2764                              <1> 	;
  2765                              <1> 	; Modified Registers -> EAX
  2766                              <1> 	;
  2767                              <1> 	;
  2768 00002631 56                  <1> 	push	esi
  2769 00002632 51                  <1> 	push	ecx
  2770 00002633 50                  <1> 	push	eax
  2771 00002634 89C6                <1> 	mov	esi, eax 
  2772 00002636 31C9                <1> 	xor	ecx, ecx
  2773                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2774                              <1> 	; it must not be deallocated
  2775 00002638 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2776                              <1> dapd_0:
  2777 0000263A AD                  <1> 	lodsd
  2778 0000263B A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2779 0000263D 7409                <1> 	jz	short dapd_1	
  2780 0000263F 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2781 00002643 E812000000          <1> 	call	deallocate_page_table			
  2782                              <1> dapd_1:
  2783 00002648 41                  <1> 	inc	ecx ; page directory entry index
  2784 00002649 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2785 0000264F 72E9                <1> 	jb	short dapd_0
  2786                              <1> dapd_2:
  2787 00002651 58                  <1> 	pop	eax
  2788 00002652 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2789 00002657 59                  <1> 	pop	ecx
  2790 00002658 5E                  <1> 	pop	esi
  2791 00002659 C3                  <1> 	retn
  2792                              <1> 
  2793                              <1> deallocate_page_table:
  2794                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2795                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2796                              <1> 	; 19/09/2015
  2797                              <1> 	; 15/09/2015
  2798                              <1> 	; 05/08/2015
  2799                              <1> 	; 30/04/2015
  2800                              <1> 	; 28/04/2015
  2801                              <1> 	; 24/10/2014
  2802                              <1> 	; 23/10/2014
  2803                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2804                              <1> 	;
  2805                              <1> 	; INPUT ->
  2806                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2807                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2808                              <1> 	;	(ECX = page directory entry index)
  2809                              <1> 	; OUTPUT ->
  2810                              <1> 	;	All of pages in the page table and page table's itself
  2811                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2812                              <1> 	;	(will be converted to writable pages).
  2813                              <1> 	;
  2814                              <1> 	; Modified Registers -> EAX
  2815                              <1> 	;
  2816 0000265A 56                  <1> 	push	esi
  2817 0000265B 57                  <1> 	push	edi
  2818 0000265C 52                  <1> 	push	edx
  2819 0000265D 50                  <1> 	push	eax ; *
  2820 0000265E 89C6                <1> 	mov	esi, eax 
  2821 00002660 31FF                <1> 	xor	edi, edi ; 0
  2822                              <1> dapt_0:
  2823 00002662 AD                  <1> 	lodsd
  2824 00002663 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2825 00002665 7455                <1> 	jz	short dapt_1
  2826                              <1> 	;
  2827 00002667 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2828                              <1> 				  ; (must be 1)
  2829 00002669 753F                <1> 	jnz	short dapt_3
  2830                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2831 0000266B 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2832                              <1> 				   ; as child's page ?
  2833 0000266F 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2834                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2835                              <1> 	; ECX = page directory entry index (0-1023)
  2836 00002671 53                  <1> 	push	ebx
  2837 00002672 51                  <1> 	push	ecx
  2838 00002673 66C1E102            <1> 	shl	cx, 2 ; *4 
  2839 00002677 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2840 00002679 8B0B                <1> 	mov	ecx, [ebx]
  2841 0000267B F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2842 0000267E 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2843 00002680 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2844                              <1> 	; EDI = page table entry index (0-1023)
  2845 00002685 89FA                <1> 	mov	edx, edi 
  2846 00002687 66C1E202            <1> 	shl	dx, 2 ; *4 
  2847 0000268B 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2848 0000268D 8B1A                <1> 	mov	ebx, [edx]
  2849 0000268F F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2850 00002692 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2851 00002694 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2852 00002698 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2853 0000269D 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2854 0000269F 7507                <1> 	jne	short dapt_2	; not same page
  2855                              <1> 				; deallocate the child's page
  2856 000026A1 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2857 000026A4 59                  <1> 	pop	ecx
  2858 000026A5 5B                  <1> 	pop	ebx
  2859 000026A6 EB0D                <1> 	jmp	short dapt_4
  2860                              <1> 
  2861                              <1> ; 24/12/2021
  2862                              <1> ; ('dapt_1' is disabled)
  2863                              <1> ;
  2864                              <1> ;dapt_1:
  2865                              <1> ;	or	eax, eax	; swapped page ?
  2866                              <1> ;	jz	short dapt_5	; no
  2867                              <1> ;				; yes
  2868                              <1> ;	shr	eax, 1
  2869                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2870                              <1> ;				  ; on the swap disk (or in file)
  2871                              <1> ;	jmp	short dapt_5
  2872                              <1> dapt_2:
  2873 000026A8 59                  <1> 	pop	ecx
  2874 000026A9 5B                  <1> 	pop	ebx
  2875                              <1> dapt_3:	
  2876                              <1> 	; 12/07/2016
  2877 000026AA 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2878 000026AE 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2879                              <1> 	;
  2880                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2881 000026B0 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2882                              <1> dapt_4:
  2883 000026B5 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2884                              <1> dapt_1:	; 24/12/2021
  2885                              <1> dapt_5:
  2886 000026BC 47                  <1> 	inc	edi ; page table entry index
  2887 000026BD 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2888 000026C3 729D                <1> 	jb	short dapt_0
  2889                              <1> 	;
  2890 000026C5 58                  <1> 	pop	eax ; *
  2891 000026C6 5A                  <1> 	pop	edx
  2892 000026C7 5F                  <1> 	pop	edi	
  2893 000026C8 5E                  <1> 	pop	esi
  2894                              <1> 	;
  2895                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2896                              <1> 	;retn
  2897                              <1> 
  2898                              <1> deallocate_page:
  2899                              <1> 	; 15/09/2015
  2900                              <1> 	; 28/04/2015
  2901                              <1> 	; 10/03/2015
  2902                              <1> 	; 17/10/2014
  2903                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2904                              <1> 	;
  2905                              <1> 	; INPUT -> 
  2906                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2907                              <1> 	; OUTPUT ->
  2908                              <1> 	;	[free_pages] is increased
  2909                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2910                              <1> 	;	CF = 1 if the page is already deallocated
  2911                              <1> 	; 	       (or not allocated) before.  
  2912                              <1> 	;
  2913                              <1> 	; Modified Registers -> EAX
  2914                              <1> 	;
  2915 000026C9 53                  <1> 	push	ebx
  2916 000026CA 52                  <1> 	push	edx
  2917                              <1> 	;
  2918 000026CB C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2919                              <1> 				     ; 12 bits right
  2920                              <1> 				     ; to get page number
  2921 000026CE 89C2                <1> 	mov	edx, eax
  2922                              <1> 	; 15/09/2015
  2923 000026D0 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2924                              <1> 				     ; (1 allocation bit = 1 page)
  2925                              <1> 				     ; (1 allocation bytes = 8 pages)
  2926 000026D3 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2927                              <1> 				     ; (to get 32 bit position)			
  2928                              <1> 	;
  2929 000026D6 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2930 000026DB 01D3                <1> 	add	ebx, edx
  2931 000026DD 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2932                              <1> 				     ; (allocation bit position)	 
  2933 000026E0 3B15[14630000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2934                              <1> 				     ; than the address in 'next_page' ?
  2935                              <1> 				     ; (next/first free page value)		
  2936 000026E6 7306                <1> 	jnb	short dap_1	     ; no	
  2937 000026E8 8915[14630000]      <1> 	mov	[next_page], edx     ; yes
  2938                              <1> dap_1:
  2939 000026EE 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2940                              <1> 				     ; set relevant bit to 1.
  2941                              <1> 				     ; set CF to the previous bit value	
  2942                              <1> 	;cmc			     ; complement carry flag	
  2943                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2944                              <1> 				     ; if the page is already deallocated
  2945                              <1> 				     ; before.	
  2946 000026F1 FF05[10630000]      <1>         inc     dword [free_pages]
  2947                              <1> dap_2:
  2948 000026F7 5A                  <1> 	pop	edx
  2949 000026F8 5B                  <1> 	pop	ebx
  2950 000026F9 C3                  <1> 	retn
  2951                              <1> 
  2952                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2953                              <1> ;;                                                              ;;
  2954                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2955                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2956                              <1> ;;                                                              ;;
  2957                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2958                              <1> 
  2959                              <1> ;;$Revision: 5057 $
  2960                              <1> 
  2961                              <1> 
  2962                              <1> ;;align 4
  2963                              <1> ;;proc alloc_page
  2964                              <1> 
  2965                              <1> ;;        pushfd
  2966                              <1> ;;        cli
  2967                              <1> ;;        push    ebx
  2968                              <1> ;;;//-
  2969                              <1> ;;        cmp     [pg_data.pages_free], 1
  2970                              <1> ;;        jle     .out_of_memory
  2971                              <1> ;;;//-
  2972                              <1> ;;
  2973                              <1> ;;        mov     ebx, [page_start]
  2974                              <1> ;;        mov     ecx, [page_end]
  2975                              <1> ;;.l1:
  2976                              <1> ;;        bsf     eax, [ebx];
  2977                              <1> ;;        jnz     .found
  2978                              <1> ;;        add     ebx, 4
  2979                              <1> ;;        cmp     ebx, ecx
  2980                              <1> ;;        jb      .l1
  2981                              <1> ;;        pop     ebx
  2982                              <1> ;;        popfd
  2983                              <1> ;;        xor     eax, eax
  2984                              <1> ;;        ret
  2985                              <1> ;;.found:
  2986                              <1> ;;;//-
  2987                              <1> ;;        dec     [pg_data.pages_free]
  2988                              <1> ;;        jz      .out_of_memory
  2989                              <1> ;;;//-
  2990                              <1> ;;        btr     [ebx], eax
  2991                              <1> ;;        mov     [page_start], ebx
  2992                              <1> ;;        sub     ebx, sys_pgmap
  2993                              <1> ;;        lea     eax, [eax+ebx*8]
  2994                              <1> ;;        shl     eax, 12
  2995                              <1> ;;;//-       dec [pg_data.pages_free]
  2996                              <1> ;;        pop     ebx
  2997                              <1> ;;        popfd
  2998                              <1> ;;        ret
  2999                              <1> ;;;//-
  3000                              <1> ;;.out_of_memory:
  3001                              <1> ;;        mov     [pg_data.pages_free], 1
  3002                              <1> ;;        xor     eax, eax
  3003                              <1> ;;        pop     ebx
  3004                              <1> ;;        popfd
  3005                              <1> ;;        ret
  3006                              <1> ;;;//-
  3007                              <1> ;;endp
  3008                              <1> 
  3009                              <1> duplicate_page_dir:
  3010                              <1> 	; 21/09/2015
  3011                              <1> 	; 31/08/2015
  3012                              <1> 	; 20/07/2015
  3013                              <1> 	; 28/04/2015
  3014                              <1> 	; 27/04/2015
  3015                              <1> 	; 18/04/2015
  3016                              <1> 	; 12/04/2015
  3017                              <1> 	; 18/10/2014
  3018                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3019                              <1> 	;
  3020                              <1> 	; INPUT -> 
  3021                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3022                              <1> 	;		    page directory.
  3023                              <1> 	; OUTPUT ->
  3024                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3025                              <1> 	;	       page directory.
  3026                              <1> 	;	(New page directory with new page table entries.)
  3027                              <1> 	;	(New page tables with read only copies of the parent's
  3028                              <1> 	;	pages.)
  3029                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3030                              <1> 	;
  3031                              <1> 	; Modified Registers -> none (except EAX)
  3032                              <1> 	;
  3033 000026FA E802FEFFFF          <1> 	call	allocate_page
  3034 000026FF 723E                <1> 	jc	short dpd_err
  3035                              <1> 	;
  3036 00002701 55                  <1> 	push	ebp ; 20/07/2015
  3037 00002702 56                  <1> 	push	esi
  3038 00002703 57                  <1> 	push	edi
  3039 00002704 53                  <1> 	push	ebx
  3040 00002705 51                  <1> 	push	ecx
  3041 00002706 8B35[1B670000]      <1> 	mov	esi, [u.pgdir]
  3042 0000270C 89C7                <1> 	mov	edi, eax
  3043 0000270E 50                  <1> 	push	eax ; save child's page directory address
  3044                              <1> 	; 31/08/2015
  3045                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3046                              <1> 	; (use same system space for all user page tables) 
  3047 0000270F A5                  <1> 	movsd
  3048 00002710 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3049 00002715 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3050                              <1> dpd_0:	
  3051 0000271A AD                  <1> 	lodsd
  3052                              <1> 	;or	eax, eax
  3053                              <1>         ;jnz     short dpd_1
  3054 0000271B A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3055 0000271D 7508                <1> 	jnz	short dpd_1
  3056                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3057 0000271F 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3058 00002725 EB0F                <1> 	jmp	short dpd_2
  3059                              <1> dpd_1:	
  3060 00002727 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3061 0000272B 89C3                <1> 	mov	ebx, eax
  3062                              <1> 	; EBX = Parent's page table address
  3063 0000272D E81F000000          <1> 	call	duplicate_page_table
  3064 00002732 720C                <1> 	jc	short dpd_p_err
  3065                              <1> 	; EAX = Child's page table address
  3066 00002734 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3067                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3068                              <1> 			 ; (present, writable, user)
  3069                              <1> dpd_2:
  3070 00002736 AB                  <1> 	stosd
  3071 00002737 E2E1                <1> 	loop	dpd_0
  3072                              <1> 	;
  3073 00002739 58                  <1> 	pop	eax  ; restore child's page directory address
  3074                              <1> dpd_3:
  3075 0000273A 59                  <1> 	pop	ecx
  3076 0000273B 5B                  <1> 	pop	ebx
  3077 0000273C 5F                  <1> 	pop	edi
  3078 0000273D 5E                  <1> 	pop	esi
  3079 0000273E 5D                  <1> 	pop	ebp ; 20/07/2015
  3080                              <1> dpd_err:
  3081 0000273F C3                  <1> 	retn
  3082                              <1> dpd_p_err:
  3083                              <1> 	; release the allocated pages missing (recover free space)
  3084 00002740 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3085 00002741 8B1D[1B670000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3086 00002747 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3087 0000274C 29C0                <1> 	sub	eax, eax ; 0
  3088 0000274E F9                  <1> 	stc
  3089 0000274F EBE9                <1> 	jmp	short dpd_3	
  3090                              <1> 
  3091                              <1> duplicate_page_table:
  3092                              <1> 	; 31/12/2021
  3093                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3094                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3095                              <1> 	; 21/09/2015
  3096                              <1> 	; 20/07/2015
  3097                              <1> 	; 05/05/2015
  3098                              <1> 	; 28/04/2015
  3099                              <1> 	; 27/04/2015
  3100                              <1> 	; 18/04/2015
  3101                              <1> 	; 18/10/2014
  3102                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3103                              <1> 	;
  3104                              <1> 	; INPUT -> 
  3105                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3106                              <1> 	;       20/02/2017		 
  3107                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3108                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3109                              <1> 	; OUTPUT ->
  3110                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3111                              <1> 	;	      (with 'read only' attribute of page table entries)
  3112                              <1> 	;	20/02/2017
  3113                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3114                              <1> 	;	
  3115                              <1> 	;	CF = 1 -> error 
  3116                              <1> 	;
  3117                              <1> 	; Modified Registers -> EBP (except EAX)
  3118                              <1> 	;
  3119 00002751 E8ABFDFFFF          <1> 	call	allocate_page
  3120 00002756 725B                <1> 	jc	short dpt_err
  3121                              <1> 	;
  3122 00002758 50                  <1> 	push	eax ; *
  3123 00002759 56                  <1> 	push	esi
  3124 0000275A 57                  <1> 	push	edi
  3125 0000275B 52                  <1> 	push	edx
  3126 0000275C 51                  <1> 	push	ecx
  3127                              <1> 	;
  3128 0000275D 89DE                <1> 	mov	esi, ebx
  3129 0000275F 89C7                <1> 	mov	edi, eax
  3130 00002761 89C2                <1> 	mov	edx, eax
  3131 00002763 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3132                              <1> dpt_0:
  3133 00002769 AD                  <1> 	lodsd
  3134 0000276A 21C0                <1> 	and	eax, eax
  3135 0000276C 7435                <1> 	jz	short dpt_3
  3136 0000276E A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3137                              <1> 	; 24/12/2021
  3138 00002770 7503                <1> 	jnz	short dpt_1
  3139                              <1> 	;jz	short dpt_p_err
  3140                              <1> 	; 31/12/2021
  3141 00002772 F9                  <1> 	stc
  3142 00002773 EB39                <1> 	jmp	short dpt_p_err
  3143                              <1> 
  3144                              <1> ; 24/12/2021
  3145                              <1> ; ('reload_page' procedure call is disabled)
  3146                              <1> ;
  3147                              <1> ;	; 20/07/2015
  3148                              <1> ;	; ebp = virtual (linear) address of the memory page
  3149                              <1> ;	call	reload_page ; 28/04/2015
  3150                              <1> ;	jc	short dpt_p_err
  3151                              <1> dpt_1:
  3152                              <1> 	; 21/09/2015
  3153 00002775 89C1                <1> 	mov	ecx, eax
  3154 00002777 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3155 0000277B F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3156 0000277E 751A                <1> 	jnz	short dpt_2
  3157                              <1> 	; Read only (parent) page
  3158                              <1> 	; 	- there is a third process which uses this page -
  3159                              <1> 	; Allocate a new page for the child process
  3160 00002780 E87CFDFFFF          <1> 	call	allocate_page
  3161 00002785 7227                <1> 	jc	short dpt_p_err
  3162 00002787 57                  <1> 	push	edi
  3163 00002788 56                  <1> 	push	esi
  3164 00002789 89CE                <1> 	mov	esi, ecx
  3165 0000278B 89C7                <1> 	mov	edi, eax
  3166 0000278D B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3167 00002792 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3168 00002794 5E                  <1> 	pop	esi
  3169 00002795 5F                  <1> 	pop	edi
  3170                              <1> 	;
  3171                              <1> 
  3172                              <1> ; 24/12/2021
  3173                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3174                              <1> ; 
  3175                              <1> ;	push	ebx
  3176                              <1> ;	push	eax
  3177                              <1> ;	; 20/07/2015
  3178                              <1> ;	mov	ebx, ebp
  3179                              <1> ;	; ebx = virtual (linear) address of the memory page
  3180                              <1> ;	call	add_to_swap_queue
  3181                              <1> ;	pop	eax
  3182                              <1> ;	pop	ebx
  3183                              <1> 
  3184                              <1> 	; 21/09/2015
  3185 00002796 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3186                              <1> 		; user + writable + present page
  3187 00002798 EB09                <1> 	jmp	short dpt_3
  3188                              <1> dpt_2:
  3189                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3190 0000279A 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3191                              <1> 		    ; (read only page!)
  3192 0000279C 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3193 0000279F 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3194                              <1> dpt_3:
  3195 000027A3 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3196                              <1> 	;
  3197 000027A4 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3198                              <1> 	;
  3199 000027AA 39D7                <1> 	cmp	edi, edx
  3200 000027AC 72BB                <1> 	jb	short dpt_0
  3201                              <1> dpt_p_err:
  3202 000027AE 59                  <1> 	pop	ecx
  3203 000027AF 5A                  <1> 	pop	edx
  3204 000027B0 5F                  <1> 	pop	edi
  3205 000027B1 5E                  <1> 	pop	esi
  3206 000027B2 58                  <1> 	pop	eax ; *
  3207                              <1> dpt_err:
  3208 000027B3 C3                  <1> 	retn
  3209                              <1> 
  3210                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3211                              <1> 	; 31/12/2021
  3212                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3213                              <1> 	; 21/09/2015
  3214                              <1> 	; 19/09/2015
  3215                              <1> 	; 17/09/2015
  3216                              <1> 	; 28/08/2015
  3217                              <1> 	; 20/07/2015
  3218                              <1> 	; 28/06/2015
  3219                              <1> 	; 03/05/2015
  3220                              <1> 	; 30/04/2015
  3221                              <1> 	; 18/04/2015
  3222                              <1> 	; 12/04/2015
  3223                              <1> 	; 30/10/2014
  3224                              <1> 	; 11/09/2014
  3225                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3226                              <1> 	;
  3227                              <1> 	; Note: This is not an interrupt/exception handler.
  3228                              <1> 	;	This is a 'page fault remedy' subroutine 
  3229                              <1> 	;	which will be called by standard/uniform
  3230                              <1> 	;	exception handler.
  3231                              <1> 	;
  3232                              <1> 	; INPUT -> 
  3233                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3234                              <1> 	;
  3235                              <1> 	;	cr2 = the virtual (linear) address 
  3236                              <1> 	;	      which has caused to page fault (19/09/2015)
  3237                              <1> 	;
  3238                              <1> 	; OUTPUT ->
  3239                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3240                              <1> 	;	EAX = 0 -> no error
  3241                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3242                              <1> 	;
  3243                              <1> 	; Modified Registers -> none (except EAX)
  3244                              <1> 	;	
  3245                              <1>         ;
  3246                              <1>         ; ERROR CODE:
  3247                              <1> 	;	 31  .....	4   3	2   1	0
  3248                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3249                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3250                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3251                              <1> 	;
  3252                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3253                              <1>     	;		a page-protection violation. When not set,
  3254                              <1> 	;		it was caused by a non-present page.
  3255                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3256                              <1> 	;		a page write. When not set, it was caused
  3257                              <1> 	;		by a page read.
  3258                              <1> 	; U : USER    -	When set, the page fault was caused 
  3259                              <1> 	;		while CPL = 3. 
  3260                              <1> 	;		This does not necessarily mean that
  3261                              <1> 	;		the page fault was a privilege violation.
  3262                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3263                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3264                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3265                              <1> 	;     FETCH	an instruction fetch
  3266                              <1> 	;
  3267                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3268                              <1> 	;  31               22                  12 11                    0
  3269                              <1> 	; +-------------------+-------------------+-----------------------+
  3270                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3271                              <1>        	; +-------------------+-------------------+-----------------------+
  3272                              <1> 	;
  3273                              <1> 
  3274                              <1> 	;; CR3 REGISTER (Control Register 3)
  3275                              <1> 	;  31                                   12             5 4 3 2   0
  3276                              <1> 	; +---------------------------------------+-------------+---+-----+
  3277                              <1>       	; |                                       |  		|P|P|     |
  3278                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3279                              <1>       	; |                                       | 		|D|T|     |
  3280                              <1>    	; +---------------------------------------+-------------+---+-----+
  3281                              <1> 	;
  3282                              <1> 	;	PWT    - WRITE THROUGH
  3283                              <1> 	;	PCD    - CACHE DISABLE		
  3284                              <1> 	;
  3285                              <1> 	;
  3286                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3287                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3288                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3289                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3290                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3291                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3292                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3293                              <1> 	;
  3294                              <1>         ;       P      - PRESENT
  3295                              <1>         ;       R/W    - READ/WRITE
  3296                              <1>         ;       U/S    - USER/SUPERVISOR
  3297                              <1> 	;	PWT    - WRITE THROUGH
  3298                              <1> 	;	PCD    - CACHE DISABLE	
  3299                              <1> 	;	A      - ACCESSED	
  3300                              <1>         ;       D      - DIRTY (IGNORED)
  3301                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3302                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3303                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3304                              <1> 	;
  3305                              <1> 	;
  3306                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3307                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3308                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3309                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3310                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3311                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3312                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3313                              <1> 	;
  3314                              <1>         ;       P      - PRESENT
  3315                              <1>         ;       R/W    - READ/WRITE
  3316                              <1>         ;       U/S    - USER/SUPERVISOR
  3317                              <1> 	;	PWT    - WRITE THROUGH
  3318                              <1> 	;	PCD    - CACHE DISABLE	
  3319                              <1> 	;	A      - ACCESSED	
  3320                              <1>         ;       D      - DIRTY
  3321                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3322                              <1> 	;	G      - GLOBAL	 
  3323                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3324                              <1> 	;
  3325                              <1> 	;
  3326                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3327                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3328                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3329                              <1>       	; |                                       |     | | | | | | |U|R| |
  3330                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3331                              <1>       	; |                                       |     | | | | | | |S|W| |
  3332                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3333                              <1> 	;
  3334                              <1>         ;       P      - PRESENT
  3335                              <1>         ;       R/W    - READ/WRITE
  3336                              <1>         ;       U/S    - USER/SUPERVISOR
  3337                              <1>         ;       D      - DIRTY
  3338                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3339                              <1> 	;
  3340                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3341                              <1> 	;
  3342                              <1> 	;
  3343                              <1> 	;; Invalid Page Table Entry
  3344                              <1> 	; 31                                                           1 0
  3345                              <1>       	; +-------------------------------------------------------------+-+
  3346                              <1>       	; |                                                             | |
  3347                              <1>       	; |                          AVAILABLE                          |0|
  3348                              <1>       	; |                                                             | |
  3349                              <1>       	; +-------------------------------------------------------------+-+
  3350                              <1> 	;
  3351                              <1> 
  3352 000027B4 53                  <1> 	push	ebx
  3353 000027B5 52                  <1> 	push	edx
  3354 000027B6 51                  <1> 	push	ecx
  3355                              <1> 	;
  3356                              <1> 	; 21/09/2015 (debugging)
  3357 000027B7 FF05[2B670000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3358 000027BD FF05[BC630000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3359                              <1> 	; 28/06/2015
  3360                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3361 000027C3 8A15[B4630000]      <1> 	mov	dl, [error_code]
  3362                              <1> 	;
  3363 000027C9 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3364                              <1> 			; sign
  3365 000027CC 7425                <1> 	jz	short pfh_alloc_np
  3366                              <1> 	; 
  3367                              <1> 	; If it is not a 'write on read only page' type page fault
  3368                              <1> 	; major page fault error with minor reason must be returned without 
  3369                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3370                              <1> 	; after return here!
  3371                              <1> 	; Page fault will be remedied, by copying page contents
  3372                              <1> 	; to newly allocated page with write permission;
  3373                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3374                              <1> 	; used for working with minimum possible memory usage. 
  3375                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3376                              <1> 	; process with 'read only' flag. If the child process attempts to
  3377                              <1> 	; write on these read only pages, page fault will be directed here
  3378                              <1> 	; for allocating a new page with same data/content. 
  3379                              <1> 	;
  3380                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3381                              <1> 	; will not force to separate CODE and DATA space 
  3382                              <1> 	; in a process/program... 
  3383                              <1> 	; CODE segment/section may contain DATA!
  3384                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3385                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3386                              <1> 	;	
  3387 000027CE F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3388                              <1> 			; sign
  3389 000027D1 7418                <1>         jz      pfh_p_err
  3390                              <1> 	; 31/08/2015
  3391 000027D3 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3392                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3393 000027D6 7413                <1>         jz	short pfh_pv_err
  3394                              <1> 	;
  3395                              <1> 	; make a new page and copy the parent's page content
  3396                              <1> 	; as the child's new page content
  3397                              <1> 	;
  3398 000027D8 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3399                              <1> 			 ; which has caused to page fault
  3400 000027DB E87C000000          <1> 	call 	copy_page
  3401 000027E0 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3402                              <1> 	;
  3403 000027E2 EB72                <1>         jmp     pfh_cpp_ok
  3404                              <1> 
  3405                              <1> 	; 31/12/2021 (short jump)
  3406                              <1> pfh_im_err:
  3407 000027E4 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3408                              <1> 			; Major (Primary) Error: Page Fault
  3409                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3410 000027E9 EB6D                <1> 	jmp	short pfh_err_retn
  3411                              <1> 
  3412                              <1> 	; 31/12/2021
  3413                              <1> pfh_p_err: ; 09/03/2015
  3414                              <1> pfh_pv_err:
  3415                              <1> 	; Page fault was caused by a protection-violation
  3416 000027EB B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3417                              <1> 			; Major (Primary) Error: Page Fault
  3418                              <1> 			; Minor (Secondary) Error: Protection violation !
  3419 000027F0 F9                  <1> 	stc
  3420 000027F1 EB65                <1> 	jmp	short pfh_err_retn
  3421                              <1> 	
  3422                              <1> pfh_alloc_np:
  3423 000027F3 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3424 000027F8 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3425                              <1> pfh_chk_cpl:
  3426                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3427                              <1> 		; (Lower 12 bits are ZERO, because 
  3428                              <1> 		;	the address is on a page boundary)
  3429 000027FA 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3430 000027FD 7505                <1> 	jnz	short pfh_um
  3431                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3432 000027FF 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3433                              <1> 			 ; of the current/active page directory
  3434                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3435                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3436 00002802 EB06                <1> 	jmp	short pfh_get_pde
  3437                              <1> 	;
  3438                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3439 00002804 8B1D[1B670000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3440                              <1> 			; Physical address of the USER's page directory
  3441                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3442                              <1> pfh_get_pde:
  3443 0000280A 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3444 0000280D 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3445                              <1> 			 ; which has been caused to page fault
  3446                              <1> 			 ;
  3447 00002810 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3448 00002813 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3449                              <1> 	;
  3450 00002816 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3451 00002818 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3452 0000281A F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3453 0000281D 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3454                              <1> 			  	  ; set/validate page directory entry
  3455 0000281F 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3456 00002824 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3457 00002826 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3458 00002828 EB16                <1> 	jmp	short pfh_get_pte
  3459                              <1> pfh_set_pde:
  3460                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3461                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3462                              <1> 	;
  3463 0000282A 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3464 0000282C 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3465 0000282E 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3466 00002830 89C3                <1> 	mov	ebx, eax
  3467 00002832 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3468 00002837 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3469                              <1> pfh_spde_1:
  3470                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3471 00002839 89C1                <1> 	mov	ecx, eax
  3472 0000283B E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3473                              <1> pfh_get_pte:
  3474 00002840 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3475                              <1> 			 ; which has been caused to page fault
  3476 00002843 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3477 00002845 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3478                              <1> 			 ; higher 20 bits of the page fault address 
  3479 00002848 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3480 0000284D C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3481 00002850 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3482                              <1> ; 24/12/2021
  3483                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3484                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3485                              <1> ; 24/12/2021
  3486                              <1> ; ('swap_in' procedure call has been disabled)
  3487                              <1> ;
  3488                              <1> ;	and	eax, eax
  3489                              <1> ;	jz	short pfh_gpte_1
  3490                              <1> ;	; 20/07/2015
  3491                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3492                              <1> ;	push	ebp ; 20/07/2015
  3493                              <1> ;	mov	ebp, cr2
  3494                              <1> ;		; ECX = physical address of the page table entry
  3495                              <1> ;		; EBX = Memory page address (physical!)
  3496                              <1> ;		; EAX = Swap disk (offset) address
  3497                              <1> ;		; EBP = virtual address (page fault address)
  3498                              <1> ;	call	swap_in
  3499                              <1> ;	pop	ebp
  3500                              <1> ;	jc      short pfh_err_retn
  3501                              <1> ;	xchg	ecx, ebx
  3502                              <1> ;		; EBX = physical address of the page table entry
  3503                              <1> ;		; ECX = new page
  3504                              <1> pfh_gpte_1:
  3505 00002852 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3506 00002854 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3507                              <1> pfh_cpp_ok:
  3508                              <1> ; 24/12/2021
  3509                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3510                              <1> ;
  3511                              <1> ;	; 20/07/2015
  3512                              <1> ;	mov	ebx, cr2
  3513                              <1> ;	call 	add_to_swap_queue
  3514                              <1> 	;
  3515                              <1> 	; The new PTE (which contains the new page) will be added to 
  3516                              <1> 	; the swap queue, here. 
  3517                              <1> 	; (Later, if memory will become insufficient, 
  3518                              <1> 	; one page will be swapped out which is at the head of 
  3519                              <1> 	; the swap queue by using FIFO and access check methods.)
  3520                              <1> 	;
  3521 00002856 31C0                <1> 	xor	eax, eax  ; 0
  3522                              <1> 	;
  3523                              <1> pfh_err_retn:
  3524 00002858 59                  <1> 	pop	ecx
  3525 00002859 5A                  <1> 	pop	edx
  3526 0000285A 5B                  <1> 	pop	ebx
  3527 0000285B C3                  <1> 	retn 
  3528                              <1> 	
  3529                              <1> copy_page:
  3530                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3531                              <1> 	; 16/04/2021
  3532                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3533                              <1> 	; 22/09/2015
  3534                              <1> 	; 21/09/2015
  3535                              <1> 	; 19/09/2015
  3536                              <1> 	; 07/09/2015
  3537                              <1> 	; 31/08/2015
  3538                              <1> 	; 20/07/2015
  3539                              <1> 	; 05/05/2015
  3540                              <1> 	; 03/05/2015
  3541                              <1> 	; 18/04/2015
  3542                              <1> 	; 12/04/2015
  3543                              <1> 	; 30/10/2014
  3544                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3545                              <1> 	;
  3546                              <1> 	; INPUT -> 
  3547                              <1> 	;	EBX = Virtual (linear) address of source page
  3548                              <1> 	;	     (Page fault address)
  3549                              <1> 	; OUTPUT ->
  3550                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3551                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3552                              <1> 	;	EAX = 0 (CF = 1) 
  3553                              <1> 	;		if there is not a free page to be allocated
  3554                              <1> 	;	(page content of the source page will be copied
  3555                              <1> 	;	onto the target/new page) 	
  3556                              <1> 	;
  3557                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3558                              <1> 	;
  3559                              <1> 
  3560                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3561                              <1> 	; INPUT: 
  3562                              <1> 	;	EBX = Virtual (linear) address of source page
  3563                              <1> 	;	     (Page fault address)
  3564                              <1> 	; OUTPUT:
  3565                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3566                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3567                              <1> 	;	EAX = 0 (CF = 1) 
  3568                              <1> 	;		if there is not a free page to be allocated
  3569                              <1> 	;	(page content of the source page will be copied
  3570                              <1> 	;	onto the target/new page) 	
  3571                              <1> 	;
  3572                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3573                              <1> 	
  3574 0000285C 56                  <1> 	push	esi ; *
  3575 0000285D 57                  <1> 	push	edi ; **
  3576                              <1> 	; 16/04/2021
  3577                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3578                              <1> 	;push	ebx ; ***
  3579                              <1> 	;push	ecx ; ****
  3580 0000285E 31F6                <1> 	xor 	esi, esi
  3581 00002860 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3582 00002863 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3583 00002865 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3584 00002868 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3585 0000286B 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3586 0000286D 031D[1B670000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3587 00002873 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3588 00002875 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3589 00002879 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3590 0000287B 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3591 00002881 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3592 00002885 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3593                              <1> 	; 07/09/2015
  3594 00002887 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3595                              <1> 				     ; read only page as a child process?)	
  3596 0000288C 7509                <1> 	jnz	short cpp_0 ; yes
  3597 0000288E 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3598 00002890 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3599 00002895 EB32                <1> 	jmp	short cpp_1
  3600                              <1> cpp_0:
  3601 00002897 89FE                <1> 	mov	esi, edi
  3602 00002899 0335[1F670000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3603 0000289F 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3604 000028A1 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3605 000028A5 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3606 000028A7 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3607 000028AD 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3608 000028B1 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3609 000028B3 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3610                              <1> 	; 21/09/2015
  3611 000028B5 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3612 000028B7 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3613                              <1> 	;
  3614 000028BB F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3615 000028BE 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3616                              <1> 	;
  3617 000028C0 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3618 000028C5 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3619 000028C7 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3620                              <1> 			    ; Convert child's page to writable page
  3621                              <1> cpp_1:
  3622 000028C9 E833FCFFFF          <1> 	call	allocate_page
  3623 000028CE 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3624 000028D0 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3625 000028D2 7405                <1> 	jz	short cpp_2
  3626                              <1> 		; Convert read only page to writable page 
  3627                              <1> 		;(for the parent of the current process)
  3628                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3629                              <1> 	; 22/09/2015
  3630 000028D4 890E                <1> 	mov	[esi], ecx
  3631 000028D6 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3632                              <1> 				 ; 1+2+4 = 7
  3633                              <1> cpp_2:
  3634 000028D9 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3635                              <1> 	; 07/09/2015
  3636 000028DB 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3637 000028DD B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3638 000028E2 F3A5                <1> 	rep	movsd ; 31/08/2015
  3639                              <1> cpp_3:		
  3640 000028E4 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3641 000028E6 8903                <1> 	mov	[ebx], eax ; Update PTE
  3642 000028E8 28C0                <1> 	sub	al, al ; clear attributes
  3643                              <1> cpp_4:
  3644                              <1> 	; 16/04/2021
  3645                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3646                              <1> 	;pop	ecx ; ****
  3647                              <1> 	;pop	ebx ; ***
  3648 000028EA 5F                  <1> 	pop	edi ; **
  3649 000028EB 5E                  <1> 	pop	esi ; *
  3650 000028EC C3                  <1> 	retn
  3651                              <1> 
  3652                              <1> ;; 28/04/2015
  3653                              <1> ;; 24/10/2014
  3654                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3655                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3656                              <1> ;;
  3657                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3658                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3659                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3660                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3661                              <1> ;;
  3662                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3663                              <1> ;;
  3664                              <1> ;; Method:
  3665                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3666                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3667                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3668                              <1> ;;	When a new page is being allocated, swap queue is updated
  3669                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3670                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3671                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3672                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3673                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3674                              <1> ;;	offset value becomes it's previous offset value - 4.
  3675                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3676                              <1> ;;	the queue/list is not shifted.
  3677                              <1> ;;	After the queue/list shift, newly allocated page is added
  3678                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3679                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3680                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3681                              <1> ;;	
  3682                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3683                              <1> ;;	the first non-accessed, writable page in the list, 
  3684                              <1> ;;	from the head to the tail. The list is shifted to left 
  3685                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3686                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3687                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3688                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3689                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3690                              <1> ;;	procedure will be failed)...
  3691                              <1> ;;
  3692                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3693                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3694                              <1> ;;	(PTE) will be added to the tail of the queue after
  3695                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3696                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3697                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3698                              <1> ;;
  3699                              <1> ;;
  3700                              <1> ;;	
  3701                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3702                              <1> ;;
  3703                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3704                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3705                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3706                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3707                              <1> ;;
  3708                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3709                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3710                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3711                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3712                              <1> ;; 		 (entire swap space must be accessed by using
  3713                              <1> ;;		 31 bit offset address) 
  3714                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3715                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3716                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3717                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3718                              <1> ;;
  3719                              <1> ;; 					
  3720                              <1> ;; Method:
  3721                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3722                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3723                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3724                              <1> ;;	Swapping out is performed by using swap page queue.
  3725                              <1> ;;
  3726                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3727                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3728                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3729                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3730                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3731                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3732                              <1> ;;	calculated by adding offset value to the swap partition's 
  3733                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3734                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3735                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3736                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3737                              <1> ;;	is in a partitioned virtual hard disk.) 
  3738                              <1> ;;
  3739                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3740                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3741                              <1> ;;
  3742                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3743                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3744                              <1> ;;
  3745                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3746                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3747                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3748                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3749                              <1> ;;	it means relevant (respective) block is in use, and, 
  3750                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3751                              <1> ;;      swap disk/file block is free.
  3752                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3753                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3754                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3755                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3756                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3757                              <1> ;;	------------------------------------------------------------
  3758                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3759                              <1> ;;	------------------------------------------------------------
  3760                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3761                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3762                              <1> ;;
  3763                              <1> ;;	..............................................................
  3764                              <1> ;;
  3765                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3766                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3767                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3768                              <1> ;;	position with value of 1 on the table is converted to swap
  3769                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3770                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3771                              <1> ;;	number of physical swap disk or virtual swap disk)
  3772                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3773                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3774                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3775                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3776                              <1> ;;	If disk write procedure returns with error or free count of 
  3777                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3778                              <1> ;;	'insufficient memory error' (cf=1). 
  3779                              <1> ;;
  3780                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3781                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3782                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3783                              <1> ;;	free blocks after a disk write error. It will return to 
  3784                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3785                              <1> ;;
  3786                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3787                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3788                              <1> ;;	address (cf=0). 
  3789                              <1> ;;
  3790                              <1> ;;	..............................................................
  3791                              <1> ;;
  3792                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3793                              <1> ;;	file sectors at specified memory page. Then page allocation
  3794                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3795                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3796                              <1> ;;	to do, except to terminate the process which is the owner of
  3797                              <1> ;;	the swapped page.
  3798                              <1> ;;
  3799                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3800                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3801                              <1> ;;	updates [swpd_first] pointer if it is required.
  3802                              <1> ;;
  3803                              <1> ;;	..............................................................	 
  3804                              <1> ;;
  3805                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3806                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3807                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3808                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3809                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3810                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3811                              <1> ;;
  3812                              <1> 
  3813                              <1> ; 24/12/2021
  3814                              <1> ; ('swap_in' procedure call is disabled)
  3815                              <1> 
  3816                              <1> ;swap_in:
  3817                              <1> 	; 31/08/2015
  3818                              <1> 	; 20/07/2015
  3819                              <1> 	; 28/04/2015
  3820                              <1> 	; 18/04/2015
  3821                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3822                              <1> 	;
  3823                              <1> 	; INPUT -> 
  3824                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3825                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3826                              <1> 	;	EAX = Offset Address for the swapped page on the
  3827                              <1> 	;	      swap disk or in the swap file.
  3828                              <1> 	;
  3829                              <1> 	; OUTPUT ->
  3830                              <1> 	;	EAX = 0 if loading at memory has been successful
  3831                              <1> 	;
  3832                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3833                              <1> 	;		  or sector not present or drive not ready
  3834                              <1> 	;	     EAX = Error code
  3835                              <1> 	;	     [u.error] = EAX 
  3836                              <1> 	;		       = The last error code for the process
  3837                              <1> 	;		         (will be reset after returning to user)	  
  3838                              <1> 	;
  3839                              <1> 	; Modified Registers -> EAX
  3840                              <1> 	;
  3841                              <1> 
  3842                              <1> ;       cmp     dword [swp_drv], 0
  3843                              <1> ;	jna	short swpin_dnp_err
  3844                              <1> ;
  3845                              <1> ;	cmp	eax, [swpd_size]
  3846                              <1> ;	jnb	short swpin_snp_err
  3847                              <1> ;
  3848                              <1> ;	push	esi
  3849                              <1> ;	push	ebx
  3850                              <1> ;	push	ecx
  3851                              <1> ;	mov	esi, [swp_drv]	
  3852                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3853                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3854                              <1> ;		; size different than 512 bytes, logical disk sector
  3855                              <1> ;		; size is 512 bytes and disk reading procedure
  3856                              <1> ;		; will be performed for reading 4096 bytes
  3857                              <1> ;		; (2*2048, 8*512). 
  3858                              <1> ;	; ESI = Logical disk description table address
  3859                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3860                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3861                              <1> ;	; ECX = Sector count ; 8 sectors
  3862                              <1> ;	push	eax
  3863                              <1> ;	call	logical_disk_read
  3864                              <1> ;	pop	eax
  3865                              <1> ;	jnc	short swpin_read_ok
  3866                              <1> ;	;
  3867                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3868                              <1> ;	mov	[u.error], eax
  3869                              <1> ;	jmp	short swpin_retn
  3870                              <1> ;	;
  3871                              <1> ;swpin_read_ok:
  3872                              <1> ;	; EAX = Offset address (logical sector number)
  3873                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3874                              <1> ;	;
  3875                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3876                              <1> ;	; 20/07/2015
  3877                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3878                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3879                              <1> ;	mov	bl, [u.uno] ; current process number
  3880                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3881                              <1> ;	call	swap_queue_shift
  3882                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3883                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3884                              <1> ;	; zf = 1
  3885                              <1> ;swpin_retn:
  3886                              <1> ;	pop	ecx
  3887                              <1> ;	pop	ebx
  3888                              <1> ;	pop	esi
  3889                              <1> ;	retn
  3890                              <1> ;
  3891                              <1> ;swpin_dnp_err:
  3892                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3893                              <1> ;swpin_err_retn:
  3894                              <1> ;	mov	[u.error], eax
  3895                              <1> ;	stc
  3896                              <1> ;	retn
  3897                              <1> ;
  3898                              <1> ;swpin_snp_err:
  3899                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3900                              <1> ;	jmp	short swpin_err_retn
  3901                              <1> 
  3902                              <1> ; 24/12/2021
  3903                              <1> ; ('swap_out' procedure call is disabled)
  3904                              <1> 
  3905                              <1> ;swap_out:
  3906                              <1> 	; 10/06/2016
  3907                              <1> 	; 07/06/2016
  3908                              <1>         ; 23/05/2016
  3909                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3910                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3911                              <1> 	;
  3912                              <1> 	; INPUT -> 
  3913                              <1> 	;	none
  3914                              <1> 	;
  3915                              <1> 	; OUTPUT ->
  3916                              <1> 	;	EAX = Physical page address (which is swapped out
  3917                              <1> 	;	      for allocating a new page)
  3918                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3919                              <1> 	;		  or sector not present or drive not ready
  3920                              <1> 	;	     EAX = Error code
  3921                              <1> 	;	     [u.error] = EAX 
  3922                              <1> 	;		       = The last error code for the process
  3923                              <1> 	;		         (will be reset after returning to user)	  
  3924                              <1> 	;
  3925                              <1> 	; Modified Registers -> none (except EAX)
  3926                              <1> 	;
  3927                              <1> 
  3928                              <1> ;	cmp 	word [swpq_count], 1
  3929                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3930                              <1> ;
  3931                              <1> ;       ;cmp    dword [swp_drv], 1
  3932                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3933                              <1> ;
  3934                              <1> ;       cmp     dword [swpd_free], 1
  3935                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3936                              <1> ;
  3937                              <1> ;	push	ebx ; *
  3938                              <1> ;swpout_1:
  3939                              <1> ;	; 10/06/2016
  3940                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3941                              <1> ;	call	swap_queue_shift
  3942                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3943                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3944                              <1> ;				       ; pointer in the swap queue
  3945                              <1> ;	; EAX = PTE value of the page
  3946                              <1> ;	; EBX = PTE address of the page
  3947                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3948                              <1> ;	;
  3949                              <1> ;	; 07/06/2016
  3950                              <1> ;	; 19/05/2016
  3951                              <1> ;	; check this page is in timer events or not
  3952                              <1> ;	
  3953                              <1> ;swpout_timer_page_0:
  3954                              <1> ;	push	edx ; **
  3955                              <1> ;
  3956                              <1> ;	; 07/06/2016
  3957                              <1> ;	cmp	byte [timer_events], 0 
  3958                              <1> ;	jna	short swpout_2
  3959                              <1> ;	;
  3960                              <1> ;	mov	dl, [timer_events]
  3961                              <1> ;
  3962                              <1> ;	push	ecx ; ***
  3963                              <1> ;	push	ebx ; ****
  3964                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3965                              <1> ;			       ; structures 
  3966                              <1> ;swpout_timer_page_1:
  3967                              <1> ;	mov	cl, [ebx]
  3968                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3969                              <1> ;	jz	short swpout_timer_page_3
  3970                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3971                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3972                              <1> ;				; of the response byte address, to
  3973                              <1> ;				; get beginning of the page address)
  3974                              <1> ;	cmp	eax, ecx
  3975                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3976                              <1> ;	
  3977                              <1> ;	; !same page!
  3978                              <1> ;	;
  3979                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3980                              <1> ;	; This page will be used by the kernel to put timer event
  3981                              <1> ;	; response (signal return) byte at the requested address;
  3982                              <1> ;	; in order to prevent a possible wrong write (while
  3983                              <1> ;	; this page is swapped out) on physical memory,
  3984                              <1> ;	; we must protect this page against to be swapped out!
  3985                              <1> ;	;
  3986                              <1> ;	pop	ebx ; ****
  3987                              <1> ;	pop	ecx ; ***
  3988                              <1> ;	pop	edx ; **
  3989                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3990                              <1> ; 
  3991                              <1> ;swpout_timer_page_2:
  3992                              <1> ;	; 07/06/2016
  3993                              <1> ;	dec	dl
  3994                              <1> ;	jz	short swpout_timer_page_4
  3995                              <1> ;swpout_timer_page_3:
  3996                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3997                              <1> ;	;jnb	short swpout_timer_page_4
  3998                              <1> ;	add	ebx, 16
  3999                              <1> ;	jmp	short swpout_timer_page_1	
  4000                              <1> ;
  4001                              <1> ;swpout_timer_page_4:
  4002                              <1> ;	pop	ebx ; ****
  4003                              <1> ;	pop	ecx ; ***
  4004                              <1> ;swpout_2:
  4005                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4006                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4007                              <1> ;	;
  4008                              <1> ;	call	link_swap_block
  4009                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4010                              <1> ;				       ; because [swpd_free] value
  4011                              <1> ;				       ; was checked at the beginging. 	
  4012                              <1> ;	pop	edx ; **
  4013                              <1> ;	pop	ebx ; *
  4014                              <1> ;	jmp	short swpout_nfspc_err 
  4015                              <1> ;swpout_3:
  4016                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4017                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4018                              <1> ;	;	
  4019                              <1> ;	push	esi ; **
  4020                              <1> ;	push	ecx ; ***
  4021                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4022                              <1> ;	mov	esi, [swp_drv]	
  4023                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4024                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4025                              <1> ;		; size different than 512 bytes, logical disk sector
  4026                              <1> ;		; size is 512 bytes and disk writing procedure
  4027                              <1> ;		; will be performed for writing 4096 bytes
  4028                              <1> ;		; (2*2048, 8*512). 
  4029                              <1> ;	; ESI = Logical disk description table address
  4030                              <1> ;	; EBX = Buffer (Page) address
  4031                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4032                              <1> ;	; ECX = Sector count ; 8 sectors
  4033                              <1> ;	; edx = PTE address
  4034                              <1> ;	call	logical_disk_write
  4035                              <1> ;	; edx = PTE address
  4036                              <1> ;	pop	ecx ; sector address	
  4037                              <1> ;	jnc	short swpout_write_ok
  4038                              <1> ;	;
  4039                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4040                              <1> ;swpout_dw_err:
  4041                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4042                              <1> ;	mov	[u.error], eax
  4043                              <1> ;	jmp	short swpout_retn
  4044                              <1> ;	;
  4045                              <1> ;swpout_write_ok:
  4046                              <1> ;	; EBX = Buffer (page) address
  4047                              <1> ;	; EDX = Page Table Entry address
  4048                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4049                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4050                              <1> ;	mov 	[edx], ecx 
  4051                              <1> ;		; bit 0 = 0 (swapped page)
  4052                              <1> ;	mov	eax, ebx
  4053                              <1> ;swpout_retn:
  4054                              <1> ;	pop	ecx ; ***
  4055                              <1> ;	pop	esi ; **
  4056                              <1> ;	pop	ebx ; *
  4057                              <1> ;	retn
  4058                              <1> ;
  4059                              <1> ;;swpout_dnp_err:
  4060                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4061                              <1> ;;	jmp	short swpout_err_retn
  4062                              <1> ;swpout_nfspc_err:
  4063                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4064                              <1> ;swpout_err_retn:
  4065                              <1> ;	mov	[u.error], eax
  4066                              <1> ;	;stc
  4067                              <1> ;	retn
  4068                              <1> ;swpout_npts_err:
  4069                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4070                              <1> ;	pop	ebx
  4071                              <1> ;	jmp	short swpout_err_retn
  4072                              <1> ;swpout_im_err:
  4073                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4074                              <1> ;	jmp	short swpout_err_retn
  4075                              <1> 
  4076                              <1> ; 24/12/2021
  4077                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4078                              <1> 
  4079                              <1> ;swap_queue_shift:
  4080                              <1> 	; 26/03/2017
  4081                              <1> 	; 10/06/2016
  4082                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4083                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4084                              <1> 	;
  4085                              <1> 	; INPUT ->
  4086                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4087                              <1> 	;	      and process number combination (bit 0 to 11)
  4088                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4089                              <1> 	;	
  4090                              <1> 	; OUTPUT ->
  4091                              <1> 	;	If EBX input > 0 
  4092                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4093                              <1> 	; 	   from the tail to the head, up to entry offset
  4094                              <1> 	; 	   which points to EBX input value or nothing
  4095                              <1> 	;	   to do if EBX value is not found on the queue.
  4096                              <1> 	;	   (The entry -with EBX value- will be removed
  4097                              <1> 	;	   from the queue if it is found.)
  4098                              <1> 	;
  4099                              <1> 	;	   EAX = 0		
  4100                              <1> 	;
  4101                              <1> 	;	If EBX input = 0
  4102                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4103                              <1> 	; 	   from the tail to the head, if the PTE address
  4104                              <1> 	;	   which is pointed in head of the queue is marked
  4105                              <1> 	;	   as "accessed" or it is marked as "non present".
  4106                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4107                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4108                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4109                              <1> 	;	   -without dropping pointer of the PTE from 
  4110                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4111                              <1> 	;	   Pointer in the head will be moved into the tail,
  4112                              <1> 	;	   other PTEs will be shifted on head direction.)
  4113                              <1> 	;
  4114                              <1> 	;	   Swap queue will be shifted up to the first
  4115                              <1> 	;	   'present' or 'non accessed' page will be found
  4116                              <1> 	;	   (as pointed) on the queue head (then it will be
  4117                              <1>         ;          removed/dropped from the queue).
  4118                              <1> 	;
  4119                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4120                              <1> 	;		 (it's pointer -virtual address-) dropped
  4121                              <1> 	;		 (removed) from swap queue.
  4122                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4123                              <1> 	;	         which is (it's pointer -virtual address-)
  4124                              <1> 	;		 dropped (removed) from swap queue.
  4125                              <1> 	;
  4126                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4127                              <1> 	;
  4128                              <1> 	; Modified Registers -> EAX, EBX
  4129                              <1> 	;
  4130                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4131                              <1> ;	and	ax, ax
  4132                              <1> ;	jz	short swpqs_retn
  4133                              <1> ;	push	edi
  4134                              <1> ;	push	esi
  4135                              <1> ;	push	ecx
  4136                              <1> ;	mov	esi, swap_queue
  4137                              <1> ;	mov	ecx, eax
  4138                              <1> ;	or	ebx, ebx
  4139                              <1> ;	jz	short swpqs_7
  4140                              <1> ;swpqs_1:
  4141                              <1> ;	lodsd
  4142                              <1> ;	cmp	eax, ebx
  4143                              <1> ;	je	short swpqs_2
  4144                              <1> ;	loop	swpqs_1
  4145                              <1> ;	; 10/06/2016
  4146                              <1> ;	sub	eax, eax 
  4147                              <1> ;	jmp	short swpqs_6
  4148                              <1> ;swpqs_2:
  4149                              <1> ;	mov	edi, esi
  4150                              <1> ;	sub 	edi, 4
  4151                              <1> ;swpqs_3:
  4152                              <1> ;	dec	word [swpq_count]
  4153                              <1> ;	jz	short swpqs_5
  4154                              <1> ;swpqs_4:
  4155                              <1> ;	dec 	ecx
  4156                              <1> ;	rep	movsd	; shift up (to the head)
  4157                              <1> ;swpqs_5:
  4158                              <1> ;	xor	eax, eax
  4159                              <1> ;	mov	[edi], eax
  4160                              <1> ;swpqs_6:
  4161                              <1> ;	pop	ecx
  4162                              <1> ;	pop	esi
  4163                              <1> ;	pop	edi
  4164                              <1> ;swpqs_retn:
  4165                              <1> ;	retn		
  4166                              <1> ;swpqs_7:
  4167                              <1> ;	mov	edi, esi ; head
  4168                              <1> ;	lodsd
  4169                              <1> ;	; 20/07/2015
  4170                              <1> ;	mov	ebx, eax
  4171                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4172                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4173                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4174                              <1> ;		      ; ax = process number (1 to 4095)
  4175                              <1> ;	cmp	al, [u.uno]
  4176                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4177                              <1> ;	jne	short swpqs_8
  4178                              <1> ;	mov	eax, [u.pgdir]
  4179                              <1> ;	jmp	short swpqs_9
  4180                              <1> ;swpqs_8:
  4181                              <1> ;	; 09/06/2016
  4182                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4183                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4184                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4185                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4186                              <1> ;
  4187                              <1> ;	;shl	ax, 2
  4188                              <1> ;	shl	al, 2
  4189                              <1> ;	mov 	eax, [eax+p.upage-4]
  4190                              <1> ;	or	eax, eax
  4191                              <1> ;	jz	short swpqs_3 ; invalid upage
  4192                              <1> ;	add	eax, u.pgdir - user
  4193                              <1> ;			 ; u.pgdir value for the process
  4194                              <1> ;			 ; is in [eax]
  4195                              <1> ;	mov	eax, [eax]
  4196                              <1> ;	and	eax, eax
  4197                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4198                              <1> ;swpqs_9:
  4199                              <1> ;	push	edx
  4200                              <1> ;	; eax = page directory
  4201                              <1> ;	; ebx = virtual address
  4202                              <1> ;	call	get_pte
  4203                              <1> ;	mov	ebx, edx	; PTE address
  4204                              <1> ;	pop	edx
  4205                              <1> ;	; 10/06/2016
  4206                              <1> ;	jc	short swpqs_13 ; empty PDE
  4207                              <1> ;	; EAX = PTE value
  4208                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4209                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4210                              <1> ;			        ; from the queue (head)
  4211                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4212                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4213                              <1> ;			        ; from the queue (head) 	
  4214                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4215                              <1> ;	;jnz	short swpqs_11  ; present
  4216                              <1> ;			        ; accessed page
  4217                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4218                              <1> ;	jc	short swpqs_11  ; accessed page
  4219                              <1> ;
  4220                              <1> ;	dec	ecx
  4221                              <1> ;	mov	[swpq_count], cx
  4222                              <1> ;       jz      short swpqs_10
  4223                              <1> ;		; esi = head + 4
  4224                              <1> ;		; edi = head
  4225                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4226                              <1> ;swpqs_10:
  4227                              <1> ;	mov	[edi], ecx ; 0
  4228                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4229                              <1> ;
  4230                              <1> ;swpqs_11:
  4231                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4232                              <1> ;	; Rotation (head -> tail)
  4233                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4234                              <1> ;	jz	short swpqs_10
  4235                              <1> ;		; esi = head + 4
  4236                              <1> ;		; edi = head
  4237                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4238                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4239                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4240                              <1> ;
  4241                              <1> ;	mov	cx, [swpq_count]
  4242                              <1> ;
  4243                              <1> ;swpqs_12:
  4244                              <1> ;	mov	esi, swap_queue ; head
  4245                              <1> ;       jmp     swpqs_7
  4246                              <1> ;
  4247                              <1> ;swpqs_13:
  4248                              <1> ;	dec	ecx
  4249                              <1> ;	mov	[swpq_count], cx
  4250                              <1> ;       jz      swpqs_5
  4251                              <1> ;	jmp	short swpqs_12
  4252                              <1> 
  4253                              <1> ; 24/12/2021
  4254                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4255                              <1> 
  4256                              <1> ;add_to_swap_queue:
  4257                              <1> 	; 20/02/2017
  4258                              <1> 	; 20/07/2015
  4259                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4260                              <1> 	;
  4261                              <1> 	; Adds new page to swap queue
  4262                              <1> 	; (page directories and page tables must not be added
  4263                              <1> 	; to swap queue)	
  4264                              <1> 	;
  4265                              <1> 	; INPUT ->
  4266                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4267                              <1> 	;	[u.uno]
  4268                              <1> 	;	20/02/2017
  4269                              <1> 	;	(Linear address = CORE + user's virtual address)
  4270                              <1> 	;
  4271                              <1> 	; OUTPUT ->
  4272                              <1> 	;	EAX = [swpq_count]
  4273                              <1> 	;	      (after the PTE has been added)
  4274                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4275                              <1> 	;	      the PTE could not be added.
  4276                              <1> 	;
  4277                              <1> 	; Modified Registers -> EAX
  4278                              <1> 	;
  4279                              <1> ;	push	ebx
  4280                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4281                              <1> ;	mov	bl, [u.uno] ; current process number
  4282                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4283                              <1> ;				 ; it is already on the queue
  4284                              <1> ;		; then add it to the tail of the queue
  4285                              <1> ;	movzx	eax, word [swpq_count]
  4286                              <1> ;	cmp	ax, 1024
  4287                              <1> ;	jb	short atsq_1
  4288                              <1> ;	sub	ax, ax
  4289                              <1> ;	pop	ebx
  4290                              <1> ;	retn
  4291                              <1> ;atsq_1:
  4292                              <1> ;	push	esi
  4293                              <1> ;	mov	esi, swap_queue
  4294                              <1> ;	and	ax, ax
  4295                              <1> ;	jz	short atsq_2
  4296                              <1> ;	shl	ax, 2	; convert to offset
  4297                              <1> ;	add	esi, eax
  4298                              <1> ;	shr	ax, 2
  4299                              <1> ;atsq_2:
  4300                              <1> ;	inc	ax
  4301                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4302                              <1> ;	mov	[swpq_count], ax
  4303                              <1> ;	pop	esi
  4304                              <1> ;	pop	ebx
  4305                              <1> ;	retn
  4306                              <1> 
  4307                              <1> ; 24/12/2021
  4308                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4309                              <1> 
  4310                              <1> ;unlink_swap_block:
  4311                              <1> 	; 15/09/2015
  4312                              <1> 	; 30/04/2015
  4313                              <1> 	; 18/04/2015
  4314                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4315                              <1> 	;
  4316                              <1> 	; INPUT -> 
  4317                              <1> 	;	EAX = swap disk/file offset address
  4318                              <1> 	;	      (bit 1 to bit 31)
  4319                              <1> 	; OUTPUT ->
  4320                              <1> 	;	[swpd_free] is increased
  4321                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4322                              <1> 	;
  4323                              <1> 	; Modified Registers -> EAX
  4324                              <1> 	;
  4325                              <1> ;	push	ebx
  4326                              <1> ;	push	edx
  4327                              <1> ;	;
  4328                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4329                              <1> ;				     ; 3 bits right
  4330                              <1> ;				     ; to get swap block/page number
  4331                              <1> ;	mov	edx, eax
  4332                              <1> ;	; 15/09/2015
  4333                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4334                              <1> ;				     ; (1 allocation bit = 1 page)
  4335                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4336                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4337                              <1> ;				     ; (to get 32 bit position)			
  4338                              <1> ;	;
  4339                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4340                              <1> ;	add	ebx, edx
  4341                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4342                              <1> ;				     ; (allocation bit position)	 
  4343                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4344                              <1> ;				     ; than the address in 'swpd_next' ?
  4345                              <1> ;				     ; (next/first free block value)		
  4346                              <1> ;	jnb	short uswpbl_1	     ; no	
  4347                              <1> ;	mov	[swpd_next], eax     ; yes	
  4348                              <1> ;uswpbl_1:
  4349                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4350                              <1> ;				     ; set relevant bit to 1.
  4351                              <1> ;				     ; set CF to the previous bit value	
  4352                              <1> ;	cmc			     ; complement carry flag	
  4353                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4354                              <1> ;				     ; if the block is already deallocated
  4355                              <1> ;				     ; before.	
  4356                              <1> ;       inc     dword [swpd_free]
  4357                              <1> ;uswpbl_2:
  4358                              <1> ;	pop	edx
  4359                              <1> ;	pop	ebx
  4360                              <1> ;	retn
  4361                              <1> 
  4362                              <1> ; 24/12/2021
  4363                              <1> ; ('link_swap_block' procedure call is disabled)
  4364                              <1> 
  4365                              <1> ;link_swap_block:
  4366                              <1> 	; 01/07/2015
  4367                              <1> 	; 18/04/2015
  4368                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4369                              <1> 	;
  4370                              <1> 	; INPUT -> none
  4371                              <1> 	;
  4372                              <1> 	; OUTPUT ->
  4373                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4374                              <1> 	;	      in sectors (corresponding 
  4375                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4376                              <1> 	;
  4377                              <1> 	;	CF = 1 and EAX = 0 
  4378                              <1> 	; 		   if there is not a free block to be allocated	
  4379                              <1> 	;
  4380                              <1> 	; Modified Registers -> none (except EAX)
  4381                              <1> 	;
  4382                              <1> 
  4383                              <1> ;	;mov	eax, [swpd_free]
  4384                              <1> ;	;and	eax, eax
  4385                              <1> ;	;jz	short out_of_swpspc
  4386                              <1> ;	;
  4387                              <1> ;	push	ebx
  4388                              <1> ;	push	ecx
  4389                              <1> ;	;
  4390                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4391                              <1> ;	mov	ecx, ebx
  4392                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4393                              <1> ;				 ; next_free_swap_block >> 5
  4394                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4395                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4396                              <1> ;lswbl_scan:
  4397                              <1> ;	cmp	ebx, ecx
  4398                              <1> ;	ja	short lswbl_notfound
  4399                              <1> ;	;
  4400                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4401                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4402                              <1> ;			   ; loads the destination with an index to
  4403                              <1> ;			   ; first set bit. (0 -> 31) 
  4404                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4405                              <1> ;	; 01/07/2015
  4406                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4407                              <1> ;			 ;
  4408                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4409                              <1> ;			 ;	  with value of 1 means 
  4410                              <1> ;			 ;	  the corresponding page is free 
  4411                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4412                              <1> ;	add	ebx, 4
  4413                              <1> ;			 ; We return back for searching next page block
  4414                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4415                              <1> ;			 ;	 we always will find at least 1 free block here.
  4416                              <1> ;	jmp    	short lswbl_scan
  4417                              <1> ;	;
  4418                              <1> ;lswbl_notfound:	
  4419                              <1> ;	sub	ecx, swap_alloc_table
  4420                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4421                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4422                              <1> ;	xor	eax, eax
  4423                              <1> ;	mov	[swpd_free], eax
  4424                              <1> ;	stc
  4425                              <1> ;lswbl_ok:
  4426                              <1> ;	pop	ecx
  4427                              <1> ;	pop	ebx
  4428                              <1> ;	retn
  4429                              <1> ;	;
  4430                              <1> ;;out_of_swpspc:
  4431                              <1> ;;	stc
  4432                              <1> ;;	retn
  4433                              <1> ;
  4434                              <1> ;lswbl_found:
  4435                              <1> ;	mov	ecx, ebx
  4436                              <1> ;	sub	ecx, swap_alloc_table
  4437                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4438                              <1> ;				 ; address/offset (to the next)
  4439                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4440                              <1> ;	;
  4441                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4442                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4443                              <1> ;				 ; in the destination.
  4444                              <1> ;				 ;
  4445                              <1> ;				 ; Reset the bit which is corresponding to the 
  4446                              <1> ;				 ; (just) allocated block.
  4447                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4448                              <1> ;	add	eax, ecx	 ; = block number
  4449                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4450                              <1> ;				 ; 1 block =  8 sectors
  4451                              <1> ;	;
  4452                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4453                              <1> ;	;
  4454                              <1> ;	; NOTE: The relevant page table entry will be updated
  4455                              <1> ;	;       according to this EAX value...
  4456                              <1> ;	;
  4457                              <1> ;	jmp	short lswbl_ok
  4458                              <1> 
  4459                              <1> ; 24/12/2021
  4460                              <1> ; ('logical_disk_read' procedure call is disabled)
  4461                              <1> 
  4462                              <1> ;logical_disk_read:
  4463                              <1> 	; 20/07/2015
  4464                              <1> 	; 09/03/2015 (temporary code here)
  4465                              <1> 	;
  4466                              <1> 	; INPUT ->
  4467                              <1> 	; 	ESI = Logical disk description table address
  4468                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4469                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4470                              <1> 	; 	ECX = Sector count
  4471                              <1> 	;
  4472                              <1> 	;
  4473                              <1> ;	retn
  4474                              <1> 
  4475                              <1> ; 24/12/2021
  4476                              <1> ; ('logical_disk_write' procedure call is disabled)
  4477                              <1> 
  4478                              <1> ;logical_disk_write:
  4479                              <1> 	; 20/07/2015
  4480                              <1> 	; 09/03/2015 (temporary code here)
  4481                              <1> 	;
  4482                              <1> 	; INPUT ->
  4483                              <1> 	; 	ESI = Logical disk description table address
  4484                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4485                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4486                              <1> 	; 	ECX = Sector count
  4487                              <1> 	;
  4488                              <1> ;	retn
  4489                              <1> 
  4490                              <1> get_physical_addr:
  4491                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4492                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4493                              <1> 	; 18/10/2015
  4494                              <1> 	; 29/07/2015
  4495                              <1> 	; 20/07/2015
  4496                              <1> 	; 04/06/2015
  4497                              <1> 	; 20/05/2015
  4498                              <1> 	; 28/04/2015
  4499                              <1> 	; 18/04/2015
  4500                              <1> 	; Get physical address
  4501                              <1> 	;     (allocates a new page for user if it is not present)
  4502                              <1> 	;	
  4503                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4504                              <1> 	; (buffer) address to physical address (of the buffer).)
  4505                              <1> 	; ('sys write', 'sys read' system calls...)
  4506                              <1> 	;
  4507                              <1> 	; INPUT ->
  4508                              <1> 	;	EBX = virtual address
  4509                              <1> 	;	u.pgdir = page directory (physical) address
  4510                              <1> 	;
  4511                              <1> 	; OUTPUT ->
  4512                              <1> 	;	EAX = physical address 
  4513                              <1> 	;	EBX = linear address	
  4514                              <1> 	;	EDX = physical address of the page frame
  4515                              <1> 	;	      (with attribute bits)
  4516                              <1> 	;	ECX = byte count within the page frame
  4517                              <1> 	;
  4518                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4519                              <1> 	;
  4520                              <1> 
  4521                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4522 000028ED A1[1B670000]        <1> 	mov	eax, [u.pgdir]
  4523                              <1> 
  4524                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4525                              <1> 	
  4526 000028F2 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4527                              <1> 	;
  4528                              <1> 	;mov	eax, [u.pgdir]
  4529 000028F8 E816FDFFFF          <1> 	call	get_pte
  4530                              <1> 		; EDX = Page table entry address (if CF=0)
  4531                              <1> 	        ;       Page directory entry address (if CF=1)
  4532                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4533                              <1> 		; EAX = Page table entry value (page address)
  4534                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4535 000028FD 731C                <1> 	jnc	short gpa_1
  4536                              <1> 	;
  4537 000028FF E8FDFBFFFF          <1> 	call	allocate_page
  4538 00002904 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4539                              <1> gpa_0:
  4540 00002906 E867FCFFFF          <1> 	call 	clear_page
  4541                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4542 0000290B 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4543                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4544                              <1> 			   ; (user, writable, present page)	
  4545 0000290D 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4546 0000290F A1[1B670000]        <1> 	mov	eax, [u.pgdir]	
  4547 00002914 E8FAFCFFFF          <1> 	call	get_pte
  4548 00002919 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4549                              <1> gpa_1:
  4550                              <1> 	; EAX = PTE value, EDX = PTE address
  4551 0000291B A801                <1> 	test 	al, PTE_A_PRESENT
  4552 0000291D 750A                <1> 	jnz	short gpa_3
  4553 0000291F 09C0                <1> 	or	eax, eax
  4554 00002921 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4555                              <1> 
  4556                              <1> ; 24/12/2021
  4557                              <1> ; ('reload_page' procedure call is disabled)
  4558 00002923 EB2C                <1> 	jmp	short gpa_im_err
  4559                              <1> 
  4560                              <1> 	; 20/07/2015
  4561                              <1> ;	push	ebp
  4562                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4563                              <1> ;	; reload swapped page
  4564                              <1> ;	call	reload_page ; 28/04/2015
  4565                              <1> ;	pop	ebp
  4566                              <1> ;	jc	short gpa_retn
  4567                              <1> gpa_2:
  4568                              <1> ; 24/12/2021
  4569                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4570                              <1> 
  4571                              <1> 	; 20/07/2015
  4572                              <1> 	; 20/05/2015
  4573                              <1> 	; add this page to swap queue
  4574                              <1> ;	push	eax 
  4575                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4576                              <1> ;	call 	add_to_swap_queue
  4577                              <1> ;	pop	eax
  4578                              <1> 		; PTE address in EDX
  4579                              <1> 		; virtual address in EBX
  4580                              <1> 	; EAX = memory page address
  4581 00002925 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4582                              <1> 				  ; present flag, bit 0 = 1
  4583                              <1> 				  ; user flag, bit 2 = 1	
  4584                              <1> 				  ; writable flag, bit 1 = 1
  4585 00002927 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4586                              <1> gpa_3:
  4587                              <1> 	; 18/10/2015
  4588 00002929 89D9                <1> 	mov	ecx, ebx
  4589 0000292B 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4590 00002931 89C2                <1> 	mov 	edx, eax
  4591 00002933 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4592 00002937 01C8                <1> 	add	eax, ecx
  4593 00002939 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4594 0000293B 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4595 00002941 F8                  <1> 	clc
  4596                              <1> gpa_retn:
  4597 00002942 C3                  <1> 	retn	
  4598                              <1> gpa_4:	
  4599 00002943 E8B9FBFFFF          <1> 	call	allocate_page
  4600 00002948 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4601 0000294A E823FCFFFF          <1> 	call	clear_page
  4602 0000294F EBD4                <1> 	jmp	short gpa_2
  4603                              <1> 
  4604                              <1> gpa_im_err:	
  4605 00002951 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4606                              <1> 				  ; Major error = 0 (No protection fault)	
  4607 00002956 C3                  <1> 	retn
  4608                              <1> 
  4609                              <1> ; 24/12/2021
  4610                              <1> ; ('reload_page' procedure call is disabled)
  4611                              <1> 
  4612                              <1> ;reload_page:
  4613                              <1> 	; 20/07/2015
  4614                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4615                              <1> 	;
  4616                              <1> 	; Reload (Restore) swapped page at memory
  4617                              <1> 	;
  4618                              <1> 	; INPUT -> 
  4619                              <1> 	;	EBP = Virtual (linear) memory address
  4620                              <1> 	;	EAX = PTE value (swap disk sector address)
  4621                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4622                              <1> 	; OUTPUT ->
  4623                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4624                              <1> 	;
  4625                              <1> 	;	CF = 1 and EAX = error code
  4626                              <1> 	;
  4627                              <1> 	; Modified Registers -> none (except EAX)
  4628                              <1> 	;
  4629                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4630                              <1> ;	push	ebx      ;
  4631                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4632                              <1> ;	call	allocate_page
  4633                              <1> ;	jc	short rlp_im_err
  4634                              <1> ;	xchg 	eax, ebx	
  4635                              <1> ;	; EBX = Physical memory (page) address
  4636                              <1> ;	; EAX = Swap disk (offset) address
  4637                              <1> ;	; EBP = Virtual (linear) memory address
  4638                              <1> ;	call	swap_in
  4639                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4640                              <1> ;	mov	eax, ebx	
  4641                              <1> ;rlp_retn:
  4642                              <1> ;	pop	ebx
  4643                              <1> ;	retn
  4644                              <1> ;	
  4645                              <1> ;rlp_im_err:	
  4646                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4647                              <1> ;				  ; Major error = 0 (No protection fault)	
  4648                              <1> ;	jmp	short rlp_retn
  4649                              <1> ;
  4650                              <1> ;rlp_swp_err:
  4651                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4652                              <1> ;	jmp	short rlp_retn
  4653                              <1> 
  4654                              <1> copy_page_dir:
  4655                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4656                              <1> 	; 19/09/2015
  4657                              <1> 	; temporary - 07/09/2015
  4658                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4659                              <1> 	;
  4660                              <1> 	; INPUT -> 
  4661                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4662                              <1> 	;		    page directory.
  4663                              <1> 	; OUTPUT ->
  4664                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4665                              <1> 	;	       page directory.
  4666                              <1> 	;	(New page directory with new page table entries.)
  4667                              <1> 	;	(New page tables with read only copies of the parent's
  4668                              <1> 	;	pages.)
  4669                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4670                              <1> 	;
  4671                              <1> 	; Modified Registers -> none (except EAX)
  4672                              <1> 	;
  4673 00002957 E8A5FBFFFF          <1> 	call	allocate_page
  4674 0000295C 723E                <1> 	jc	short cpd_err
  4675                              <1> 	;
  4676 0000295E 55                  <1> 	push	ebp ; 20/07/2015
  4677 0000295F 56                  <1> 	push	esi
  4678 00002960 57                  <1> 	push	edi
  4679 00002961 53                  <1> 	push	ebx
  4680 00002962 51                  <1> 	push	ecx
  4681 00002963 8B35[1B670000]      <1> 	mov	esi, [u.pgdir]
  4682 00002969 89C7                <1> 	mov	edi, eax
  4683 0000296B 50                  <1> 	push	eax ; save child's page directory address
  4684                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4685                              <1> 	; (use same system space for all user page tables) 
  4686 0000296C A5                  <1> 	movsd
  4687 0000296D BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4688 00002972 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4689                              <1> cpd_0:	
  4690 00002977 AD                  <1> 	lodsd
  4691                              <1> 	;or	eax, eax
  4692                              <1>         ;jnz	short cpd_1
  4693 00002978 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4694 0000297A 7508                <1> 	jnz	short cpd_1
  4695                              <1>  	; (virtual address at the end of the page table)	
  4696 0000297C 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4697 00002982 EB0F                <1> 	jmp	short cpd_2
  4698                              <1> cpd_1:	
  4699 00002984 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4700 00002988 89C3                <1> 	mov	ebx, eax
  4701                              <1> 	; EBX = Parent's page table address
  4702 0000298A E81F000000          <1> 	call	copy_page_table
  4703 0000298F 720C                <1> 	jc	short cpd_p_err
  4704                              <1> 	; EAX = Child's page table address
  4705 00002991 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4706                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4707                              <1> 			 ; (present, writable, user)
  4708                              <1> cpd_2:
  4709 00002993 AB                  <1> 	stosd
  4710 00002994 E2E1                <1> 	loop	cpd_0
  4711                              <1> 	;
  4712 00002996 58                  <1> 	pop	eax  ; restore child's page directory address
  4713                              <1> cpd_3:
  4714 00002997 59                  <1> 	pop	ecx
  4715 00002998 5B                  <1> 	pop	ebx
  4716 00002999 5F                  <1> 	pop	edi
  4717 0000299A 5E                  <1> 	pop	esi
  4718 0000299B 5D                  <1> 	pop	ebp
  4719                              <1> cpd_err:
  4720 0000299C C3                  <1> 	retn
  4721                              <1> cpd_p_err:
  4722                              <1> 	; release the allocated pages missing (recover free space)
  4723 0000299D 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4724 0000299E 8B1D[1B670000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4725 000029A4 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4726 000029A9 29C0                <1> 	sub	eax, eax ; 0
  4727 000029AB F9                  <1> 	stc
  4728 000029AC EBE9                <1> 	jmp	short cpd_3	
  4729                              <1> 
  4730                              <1> copy_page_table:
  4731                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4732                              <1> 	; 19/09/2015
  4733                              <1> 	; temporary - 07/09/2015
  4734                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4735                              <1> 	;
  4736                              <1> 	; INPUT -> 
  4737                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4738                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4739                              <1> 	; OUTPUT ->
  4740                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4741                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4742                              <1> 	;	CF = 1 -> error 
  4743                              <1> 	;
  4744                              <1> 	; Modified Registers -> EBP (except EAX)
  4745                              <1> 	;
  4746 000029AE E84EFBFFFF          <1> 	call	allocate_page
  4747 000029B3 7244                <1> 	jc	short cpt_err
  4748                              <1> 	;
  4749 000029B5 50                  <1> 	push	eax ; *
  4750                              <1> 	;push 	ebx
  4751 000029B6 56                  <1> 	push	esi
  4752 000029B7 57                  <1> 	push	edi
  4753 000029B8 52                  <1> 	push	edx
  4754 000029B9 51                  <1> 	push	ecx
  4755                              <1> 	;
  4756 000029BA 89DE                <1> 	mov	esi, ebx
  4757 000029BC 89C7                <1> 	mov	edi, eax
  4758 000029BE 89C2                <1> 	mov	edx, eax
  4759 000029C0 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4760                              <1> cpt_0:
  4761 000029C6 AD                  <1> 	lodsd
  4762 000029C7 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4763                              <1> 	;jnz	short cpt_1 (*)
  4764                              <1> 	; 24/12/2021
  4765                              <1> 	;and	eax, eax (*)
  4766 000029C9 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4767                              <1> 	
  4768                              <1> ; 24/12/2021
  4769                              <1> ; ('reload_page' procedure call is disabled)
  4770                              <1> ;
  4771                              <1> ;	; ebp = virtual (linear) address of the memory page
  4772                              <1> ;	call	reload_page ; 28/04/2015
  4773                              <1> ;	jc	short cpt_p_err
  4774                              <1> cpt_1:
  4775 000029CB 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4776 000029CF 89C1                <1> 	mov	ecx, eax
  4777                              <1> 	; Allocate a new page for the child process
  4778 000029D1 E82BFBFFFF          <1> 	call	allocate_page
  4779 000029D6 721C                <1> 	jc	short cpt_p_err
  4780 000029D8 57                  <1> 	push	edi
  4781 000029D9 56                  <1> 	push	esi
  4782 000029DA 89CE                <1> 	mov	esi, ecx
  4783 000029DC 89C7                <1> 	mov	edi, eax
  4784 000029DE B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4785 000029E3 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4786 000029E5 5E                  <1> 	pop	esi
  4787 000029E6 5F                  <1> 	pop	edi
  4788                              <1> 	; 
  4789                              <1> ; 24/12/2021
  4790                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4791                              <1> ;
  4792                              <1> ;	push	ebx
  4793                              <1> ;	push	eax
  4794                              <1> ;	mov	ebx, ebp
  4795                              <1> ;	; ebx = virtual address of the memory page
  4796                              <1> ;	call	add_to_swap_queue
  4797                              <1> ;	pop	eax
  4798                              <1> ;	pop	ebx
  4799                              <1> 	;
  4800                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4801 000029E7 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4802                              <1> cpt_2:
  4803 000029E9 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4804                              <1> 	;
  4805 000029EA 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4806                              <1> 	;
  4807 000029F0 39D7                <1> 	cmp	edi, edx
  4808 000029F2 72D2                <1> 	jb	short cpt_0
  4809                              <1> cpt_p_err:
  4810 000029F4 59                  <1> 	pop	ecx
  4811 000029F5 5A                  <1> 	pop	edx
  4812 000029F6 5F                  <1> 	pop	edi
  4813 000029F7 5E                  <1> 	pop	esi
  4814                              <1> 	;pop	ebx
  4815 000029F8 58                  <1> 	pop	eax ; *
  4816                              <1> cpt_err:
  4817 000029F9 C3                  <1> 	retn
  4818                              <1> 
  4819                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4820                              <1> 
  4821                              <1> ;; Data:
  4822                              <1> 
  4823                              <1> ; 09/03/2015
  4824                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4825                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4826                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4827                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4828                              <1> ;swpd_next:  dd 0 ; next free page block
  4829                              <1> ;swpd_last:  dd 0 ; last swap page block
  2047                                  %include 'sysdefs.inc' ; 09/03/2015
  2048                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYSDEFS.INC
  2049                              <1> ; Last Modification: 13/06/2022
  2050                              <1> ;
  2051                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2052                              <1> ; (Modified from 
  2053                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2054                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2055                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2056                              <1> ; ----------------------------------------------------------------------------
  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> ; ****************************************************************************
  2064                              <1> 
  2065                              <1> nproc 	equ	16  ; number of processes
  2066                              <1> nfiles 	equ	50
  2067                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2068                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2069                              <1> 
  2070                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2071                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2072                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2073                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2074                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2075                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2076                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2077                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2078                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2079                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2080                              <1> 	; '/core' dump file size = 32768 bytes
  2081                              <1>  
  2082                              <1> ; 08/03/2014 
  2083                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2084                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2085                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2086                              <1> 
  2087                              <1> ; 30/08/2013
  2088                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2089                              <1> 
  2090                              <1> ; 05/02/2014
  2091                              <1> ; process status
  2092                              <1> ;SFREE 	equ 0
  2093                              <1> ;SRUN	equ 1
  2094                              <1> ;SWAIT	equ 2
  2095                              <1> ;SZOMB	equ 3
  2096                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2097                              <1> 
  2098                              <1> ; 09/03/2015
  2099                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2100                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2101                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2102                              <1> 
  2103                              <1> ; 17/09/2015
  2104                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2105                              <1> 
  2106                              <1> ; 21/09/2015 (36) 
  2107                              <1> ; 01/07/2015 (35)
  2108                              <1> ; 14/07/2013 (0-34)
  2109                              <1> ; UNIX v1 system calls
  2110                              <1> _rele 	equ 0
  2111                              <1> _exit 	equ 1
  2112                              <1> _fork 	equ 2
  2113                              <1> _read 	equ 3
  2114                              <1> _write	equ 4
  2115                              <1> _open	equ 5
  2116                              <1> _close 	equ 6
  2117                              <1> _wait 	equ 7
  2118                              <1> _creat 	equ 8
  2119                              <1> _link 	equ 9
  2120                              <1> _unlink	equ 10
  2121                              <1> _exec	equ 11
  2122                              <1> _chdir	equ 12
  2123                              <1> _time 	equ 13
  2124                              <1> _mkdir 	equ 14
  2125                              <1> _chmod	equ 15
  2126                              <1> _chown	equ 16
  2127                              <1> _break	equ 17
  2128                              <1> _stat	equ 18
  2129                              <1> _seek	equ 19
  2130                              <1> _tell 	equ 20
  2131                              <1> _mount	equ 21
  2132                              <1> _umount	equ 22
  2133                              <1> _setuid	equ 23
  2134                              <1> _getuid	equ 24
  2135                              <1> _stime	equ 25
  2136                              <1> _quit	equ 26	
  2137                              <1> _intr	equ 27
  2138                              <1> _fstat	equ 28
  2139                              <1> _emt 	equ 29
  2140                              <1> _mdate 	equ 30
  2141                              <1> _stty 	equ 31
  2142                              <1> _gtty	equ 32
  2143                              <1> _ilgins	equ 33
  2144                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2145                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2146                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2147                              <1> 
  2148                              <1> %macro sys 1-4
  2149                              <1>     ; 13/04/2015
  2150                              <1>     ; Retro UNIX 386 v1 system call.		
  2151                              <1>     mov eax, %1
  2152                              <1>     %if %0 >= 2   
  2153                              <1>         mov ebx, %2
  2154                              <1>         %if %0 >= 3    
  2155                              <1>             mov ecx, %3
  2156                              <1>             %if %0 = 4
  2157                              <1>                mov edx, %4   
  2158                              <1>             %endif
  2159                              <1>         %endif
  2160                              <1>     %endif
  2161                              <1>     int 30h	   
  2162                              <1> %endmacro
  2163                              <1> 
  2164                              <1> ; 13/05/2015 - ERROR CODES
  2165                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2166                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2167                              <1> ; 14/05/2015
  2168                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2169                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2170                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2171                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2172                              <1> ; 16/05/2015		
  2173                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2174                              <1> ; 18/05/2015
  2175                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2176                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2177                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2178                              <1> ; 07/06/2015
  2179                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2180                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2181                              <1> ; 09/06/2015
  2182                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2183                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2184                              <1> ; 16/06/2015
  2185                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2186                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2187                              <1> ; 22/06/2015
  2188                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2189                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2190                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2191                              <1> ; 23/06/2015
  2192                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2193                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2194                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2195                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2196                              <1> ; 27/06/2015
  2197                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2198                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2199                              <1> ; 29/06/2015
  2200                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2201                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2202                              <1> ; 12/02/2022 
  2203                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2204                              <1> ; 10/10/2016
  2205                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2206                              <1> ; 18/05/2016
  2207                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2208                              <1> ; 15/10/2016
  2209                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2210                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2211                              <1> ; 16/10/2016
  2212                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2213                              <1> ; 08/02/2022
  2214                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2215                              <1> 
  2216                              <1> ; 13/06/2022
  2217                              <1> ; printer errors
  2218                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2219                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2220                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2221                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2222                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error	
  2223                              <1> 
  2224                              <1> ; 26/08/2015
  2225                              <1> ; 24/07/2015
  2226                              <1> ; 24/06/2015
  2227                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2228                              <1> ; 01/07/2015
  2229                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2230                              <1> ;	 					 		
  2048                                  %include 'u0.s'        ; 15/03/2015
  2049                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS0.INC
  2050                              <1> ; Last Modification: 02/06/2022
  2051                              <1> ; ----------------------------------------------------------------------------
  2052                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2053                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2054                              <1> ;
  2055                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2056                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2057                              <1> ; <Bell Laboratories (17/3/1972)>
  2058                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2059                              <1> ;
  2060                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2061                              <1> ;
  2062                              <1> ; ****************************************************************************
  2063                              <1> ; 21/11/2015
  2064                              <1> 
  2065                              <1> sys_init:
  2066                              <1> 	; 27/02/2022
  2067                              <1> 	; 23/02/2022
  2068                              <1> 	; 04/02/2022
  2069                              <1> 	; 18/10/2015
  2070                              <1> 	; 28/08/2015
  2071                              <1> 	; 24/08/2015
  2072                              <1> 	; 14/08/2015
  2073                              <1> 	; 24/07/2015 
  2074                              <1> 	; 02/07/2015
  2075                              <1> 	; 01/07/2015
  2076                              <1> 	; 23/06/2015
  2077                              <1> 	; 15/04/2015
  2078                              <1> 	; 13/04/2015
  2079                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2080                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2081                              <1> 	;
  2082                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2083                              <1> 	;
  2084                              <1> 	; 14/02/2014
  2085                              <1> 	; 14/07/2013
  2086                              <1> 	;;mov	ax, 41
  2087                              <1> 	; 27/02/2022
  2088                              <1> 	;xor	eax, eax
  2089                              <1> 	;mov	al, 41
  2090                              <1> 	;mov	[rootdir], ax
  2091                              <1> 	;mov	[u.cdir], ax
  2092                              <1> 	;;and	al, 1 ; 15/04/2015
  2093                              <1> 	;inc	al  ; ax = 1
  2094 000029FA B001                <1> 	mov	al, 1
  2095 000029FC A2[11670000]        <1> 	mov	[u.uno], al
  2096                              <1> 	;mov	[mpid], ax
  2097                              <1> 	;mov	[p.pid], ax
  2098 00002A01 A2[B6660000]        <1> 	mov	[mpid], al
  2099 00002A06 A2[E4630000]        <1> 	mov	[p.pid], al	
  2100 00002A0B A2[44640000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2101                              <1> 	; 27/02/2022
  2102 00002A10 B029                <1> 	mov	al, 41
  2103                              <1> 	;mov	[rootdir], ax
  2104                              <1> 	;mov	[u.cdir], ax
  2105 00002A12 A2[B8660000]        <1> 	mov	[rootdir], al
  2106 00002A17 A2[CC660000]        <1> 	mov	[u.cdir], al
  2107                              <1> 	;
  2108                              <1> 	; 23/02/2022
  2109                              <1>  	;call	epoch
  2110                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2111                              <1> 	; 17/07/2013
  2112 00002A1C E88B060000          <1> 	call 	bf_init ; buffer initialization
  2113                              <1> 	; 23/02/2022
  2114                              <1> 	; (save sysinit time on sb0)
  2115 00002A21 E830030000          <1> 	call	epoch
  2116 00002A26 A3[0C750000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2117                              <1> 	; 23/06/2015
  2118 00002A2B E8D1FAFFFF          <1> 	call	allocate_page
  2119                              <1> 	;;jc	error
  2120                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2121                              <1> 	; 04/02/2022
  2122 00002A30 7305                <1> 	jnc	short sysinit_1
  2123 00002A32 E990000000          <1> 	jmp	panic
  2124                              <1> sysinit_1:
  2125 00002A37 A3[12670000]        <1> 	mov	[u.upage], eax ; user structure page	
  2126 00002A3C A3[54640000]        <1> 	mov	[p.upage], eax
  2127                              <1> 	;
  2128 00002A41 E82CFBFFFF          <1> 	call	clear_page
  2129                              <1> 	;
  2130                              <1> 	; 14/08/2015
  2131 00002A46 FA                  <1> 	cli
  2132                              <1> 	; 14/03/2015
  2133                              <1> 	; 17/01/2014
  2134 00002A47 E8D7010000          <1> 	call	sp_init ; serial port initialization
  2135                              <1> 	; 14/08/2015
  2136 00002A4C FB                  <1> 	sti
  2137                              <1> 	;
  2138                              <1> 	; 30/06/2015
  2139                              <1> 	;mov	esi, kernel_init_ok_msg
  2140                              <1> 	;call 	print_msg
  2141                              <1> 	;
  2142 00002A4D 30DB                <1> 	xor	bl, bl ; video page 0
  2143                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2144 00002A4F E8400F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2145 00002A54 FEC3                <1> 	inc	bl
  2146 00002A56 80FB08              <1> 	cmp	bl, 8
  2147 00002A59 72F4                <1> 	jb	short vp_clr_nxt
  2148                              <1> 	;
  2149                              <1> 	; 24/07/2015
  2150                              <1> 	;push	KDATA
  2151                              <1>         ;push	esp
  2152                              <1> 	;mov	[tss.esp0], esp
  2153                              <1>         ;mov	word [tss.ss0], KDATA
  2154                              <1> 	;
  2155                              <1> 	; 27/02/2022
  2156                              <1> 	; 24/08/2015
  2157                              <1> 	;; temporary (01/07/2015)
  2158                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2159                              <1> 			       ; it is not needed here !
  2160                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2161 00002A5B FE0D[BF660000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2162                              <1> 			      ; 0 = executing a system call
  2163                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2164                              <1> 	;
  2165                              <1> 	;;; 06/08/2015
  2166                              <1> 	;;;call	getch ; wait for a key stroke
  2167                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2168                              <1> ;;sys_init_msg_wait:
  2169                              <1> ;;	push 	ecx
  2170                              <1> ;;	mov	al, 1
  2171                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2172                              <1> ;;	call	getc_n
  2173                              <1> ;;	pop	ecx
  2174                              <1> ;;	jnz	short sys_init_msg_ok
  2175                              <1> ;;	loop	sys_init_msg_wait
  2176                              <1> 	;
  2177                              <1> ;;sys_init_msg_ok:
  2178                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2179 00002A61 6A10                <1> 	push	KDATA ; ss
  2180 00002A63 54                  <1> 	push	esp
  2181 00002A64 9C                  <1> 	pushfd
  2182 00002A65 6A08                <1> 	push	KCODE ; cs
  2183 00002A67 68[9B2A0000]        <1> 	push	init_exec ; eip
  2184 00002A6C 8925[C0660000]      <1> 	mov	[u.sp], esp
  2185 00002A72 1E                  <1> 	push	ds
  2186 00002A73 06                  <1> 	push	es
  2187 00002A74 0FA0                <1> 	push	fs
  2188 00002A76 0FA8                <1> 	push	gs	
  2189 00002A78 60                  <1> 	pushad
  2190 00002A79 8925[C4660000]      <1> 	mov	[u.usp], esp
  2191 00002A7F E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2192                              <1> 		      ; and interrupt return components (for IRET)
  2193 00002A84 61                  <1> 	popad
  2194 00002A85 6658                <1> 	pop	ax ; gs
  2195 00002A87 6658                <1> 	pop	ax ; fs
  2196 00002A89 6658                <1> 	pop	ax ; es
  2197 00002A8B 6658                <1> 	pop	ax ; ds	
  2198 00002A8D 58                  <1> 	pop	eax ; eip (init_exec)
  2199 00002A8E 6658                <1> 	pop	ax ; cs (KCODE)
  2200 00002A90 58                  <1> 	pop	eax ; E-FLAGS
  2201 00002A91 58                  <1> 	pop	eax ; esp
  2202 00002A92 6658                <1> 	pop	ax ; ss (KDATA)
  2203                              <1> 	;
  2204 00002A94 31C0                <1> 	xor	eax, eax ; 0
  2205 00002A96 A3[1F670000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2206                              <1> 	;
  2207                              <1> 	; 02/07/2015
  2208                              <1> 	; [u.pgdir ] = [k_page_dir]
  2209                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2210                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2211                              <1> init_exec:
  2212                              <1> 	; 13/03/2013
  2213                              <1> 	; 24/07/2013
  2214 00002A9B BB[BD2A0000]        <1> 	mov	ebx, init_file
  2215 00002AA0 B9[B52A0000]        <1> 	mov	ecx, init_argp
  2216                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2217                              <1> 	; ECX contains address of argument list pointer
  2218                              <1> 	;
  2219                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2220                              <1> 			      ; 0 = executing a system call
  2221                              <1> 	sys	_exec  ; execute file
  2149                              <2> 
  2150                              <2> 
  2151 00002AA5 B80B000000          <2>  mov eax, %1
  2152                              <2>  %if %0 >= 2
  2153                              <2>  mov ebx, %2
  2154                              <2>  %if %0 >= 3
  2155                              <2>  mov ecx, %3
  2156                              <2>  %if %0 = 4
  2157                              <2>  mov edx, %4
  2158                              <2>  %endif
  2159                              <2>  %endif
  2160                              <2>  %endif
  2161 00002AAA CD30                <2>  int 30h
  2222 00002AAC 7319                <1> 	jnc	short panic
  2223                              <1> 	;
  2224 00002AAE BE[1E600000]        <1> 	mov	esi, etc_init_err_msg
  2225                              <1> 	; 27/02/2022
  2226                              <1> 	;call 	print_msg
  2227 00002AB3 EB17                <1> 	jmp	short key_to_reboot
  2228                              <1> 
  2229                              <1> ;align 4
  2230                              <1> init_argp:
  2231 00002AB5 [BD2A0000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2232                              <1> init_file:
  2233                              <1> 	; 24/08/2015
  2234 00002ABD 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2234 00002AC6 00                  <1>
  2235                              <1> panic:
  2236                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2237                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2238 00002AC7 BE[03600000]        <1> 	mov 	esi, panic_msg
  2239                              <1> key_to_reboot: ; 27/02/2022
  2240 00002ACC E819000000          <1> 	call 	print_msg
  2241                              <1> ;key_to_reboot:
  2242                              <1> 	; 15/11/2015
  2243 00002AD1 E8792C0000          <1> 	call 	getch 
  2244                              <1> 		; wait for a character from the current tty
  2245                              <1> 	;
  2246 00002AD6 B00A                <1> 	mov	al, 0Ah
  2247 00002AD8 8A1D[36630000]      <1> 	mov	bl, [ptty] ; [active_page]
  2248 00002ADE B407                <1> 	mov	ah, 07h ; Black background, 
  2249                              <1> 			; light gray forecolor
  2250 00002AE0 E8D7E8FFFF          <1> 	call 	write_tty
  2251 00002AE5 E976E5FFFF          <1> 	jmp	cpu_reset 
  2252                              <1> 
  2253                              <1> print_msg:
  2254                              <1> 	; 01/07/2015
  2255                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2256                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2257                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2258                              <1> 	;
  2259                              <1> 	;
  2260 00002AEA AC                  <1> 	lodsb
  2261                              <1> pmsg1:
  2262 00002AEB 56                  <1> 	push 	esi
  2263 00002AEC 0FB61D[36630000]    <1> 	movzx	ebx, byte [ptty]
  2264 00002AF3 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2265 00002AF5 E8C2E8FFFF          <1> 	call 	write_tty
  2266 00002AFA 5E                  <1> 	pop	esi
  2267 00002AFB AC                  <1> 	lodsb
  2268 00002AFC 20C0                <1> 	and 	al, al
  2269 00002AFE 75EB                <1> 	jnz 	short pmsg1
  2270 00002B00 C3                  <1> 	retn
  2271                              <1> 	
  2272                              <1> ctrlbrk:
  2273                              <1> 	; 04/02/2022
  2274                              <1> 	; 01/02/2022
  2275                              <1> 	; 12/11/2015
  2276                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2277                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2278                              <1> 	;
  2279                              <1> 	; INT 1Bh (control+break) handler
  2280                              <1> 	;
  2281                              <1>       	; Retro Unix 8086 v1 feature only!
  2282                              <1>       	;
  2283 00002B01 66833D[06670000]00  <1> 	cmp 	word [u.intr], 0
  2284 00002B09 764B                <1> 	jna 	short cbrk4
  2285                              <1> cbrk0:
  2286                              <1> 	; 12/11/2015
  2287                              <1> 	; 06/12/2013
  2288 00002B0B 66833D[08670000]00  <1> 	cmp 	word [u.quit], 0
  2289 00002B13 7441                <1> 	jz	short cbrk4
  2290                              <1> 	;
  2291                              <1> 	; 20/09/2013	
  2292                              <1> 	;push 	ax
  2293                              <1> 	; 01/02/2022
  2294 00002B15 50                  <1> 	push	eax
  2295                              <1> 
  2296                              <1> 	; 04/02/2022
  2297                              <1> 	; (repetitive ctrl+brk check) 
  2298 00002B16 66A1[08670000]      <1> 	mov	ax, [u.quit]
  2299 00002B1C 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2300 00002B1E 7435                <1> 	jz	short cbrk3
  2301                              <1> 
  2302                              <1> 	; 20/09/2013
  2303 00002B20 A0[36630000]        <1> 	mov	al, [ptty]
  2304                              <1> 	;
  2305                              <1> 	; 12/11/2015
  2306                              <1> 	;
  2307                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2308                              <1> 	; or ctrl+break from console (pseudo) tty
  2309                              <1> 	; (!redirection!)
  2310                              <1> 	;
  2311 00002B25 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2312 00002B27 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2313                              <1> 	;	
  2314                              <1> 	; Serial port interrupt handler sets [ptty]
  2315                              <1> 	; to the port's tty number (as temporary).
  2316                              <1> 	;
  2317                              <1> 	; If active process is using a stdin or 
  2318                              <1> 	; stdout redirection (by the shell),
  2319                              <1>         ; console tty keyboard must be available
  2320                              <1> 	; to terminate running process,
  2321                              <1> 	; in order to prevent a deadlock. 
  2322                              <1> 	;
  2323 00002B29 52                  <1> 	push	edx
  2324 00002B2A 0FB615[11670000]    <1> 	movzx	edx, byte [u.uno]
  2325 00002B31 3A82[23640000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2326 00002B37 5A                  <1> 	pop	edx
  2327 00002B38 7412                <1> 	je	short cbrk2
  2328                              <1> cbrk1:
  2329 00002B3A FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2330                              <1> 	; 06/12/2013
  2331 00002B3C 3A05[F8660000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2332 00002B42 7408                <1> 	je	short cbrk2	
  2333 00002B44 3A05[F9660000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2334 00002B4A 7509                <1> 	jne	short cbrk3	
  2335                              <1> cbrk2:
  2336                              <1> 	;; 06/12/2013
  2337                              <1> 	;mov	ax, [u.quit]
  2338                              <1> 	;and	ax, ax
  2339                              <1> 	;jz	short cbrk3
  2340                              <1> 	;
  2341                              <1> 	;xor	ax, ax ; 0
  2342                              <1> 	;dec	ax
  2343                              <1> 	; 01/02/2022
  2344 00002B4C 31C0                <1> 	xor	eax, eax ; 0
  2345 00002B4E 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2346                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2347 00002B4F 66A3[08670000]      <1> 	mov	[u.quit], ax
  2348                              <1> cbrk3:
  2349                              <1> 	;pop	ax
  2350                              <1> 	; 01/02/2022
  2351 00002B55 58                  <1> 	pop	eax
  2352                              <1> cbrk4:
  2353 00002B56 C3                  <1> 	retn
  2354                              <1> 
  2355                              <1> com2_int:
  2356                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2357                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2358                              <1> 	; 07/11/2015 
  2359                              <1> 	; 24/10/2015
  2360                              <1> 	; 23/10/2015
  2361                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2362                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2363                              <1> 	; < serial port 2 interrupt handler >
  2364                              <1> 	;
  2365 00002B57 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2366                              <1> 	;;push	eax
  2367                              <1> 	; 08/01/2022
  2368 00002B5A 29C0                <1> 	sub	eax, eax
  2369 00002B5C B009                <1> 	mov	al, 9
  2370                              <1> 	;mov	ax, 9
  2371 00002B5E EB07                <1> 	jmp	short comm_int
  2372                              <1> com1_int:
  2373                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2374                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2375                              <1> 	; 07/11/2015
  2376                              <1> 	; 24/10/2015
  2377 00002B60 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2378                              <1> 	; 23/10/2015
  2379                              <1> 	;push	eax
  2380                              <1> 	; 08/01/2022
  2381 00002B63 29C0                <1> 	sub	eax, eax
  2382 00002B65 B008                <1> 	mov	al, 8
  2383                              <1> 	;mov	ax, 8
  2384                              <1> comm_int:
  2385                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2386                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2387                              <1> 	; 20/11/2015
  2388                              <1> 	; 18/11/2015
  2389                              <1> 	; 17/11/2015
  2390                              <1> 	; 16/11/2015
  2391                              <1> 	; 09/11/2015
  2392                              <1> 	; 08/11/2015
  2393                              <1> 	; 07/11/2015
  2394                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2395                              <1> 	; 01/11/2015
  2396                              <1> 	; 26/10/2015
  2397                              <1> 	; 23/10/2015
  2398 00002B67 53                  <1> 	push	ebx
  2399 00002B68 56                  <1> 	push	esi
  2400 00002B69 57                  <1> 	push	edi
  2401 00002B6A 1E                  <1> 	push 	ds
  2402 00002B6B 06                  <1> 	push 	es
  2403                              <1> 	; 18/11/2015
  2404 00002B6C 0F20DB              <1> 	mov	ebx, cr3
  2405 00002B6F 53                  <1> 	push	ebx ; ****
  2406                              <1> 	;
  2407 00002B70 51                  <1> 	push	ecx ; ***
  2408 00002B71 52                  <1> 	push	edx ; **
  2409                              <1> 	;
  2410 00002B72 BB10000000          <1> 	mov	ebx, KDATA
  2411 00002B77 8EDB                <1> 	mov	ds, bx
  2412 00002B79 8EC3                <1> 	mov	es, bx
  2413                              <1> 	;
  2414 00002B7B 8B0D[08630000]      <1> 	mov	ecx, [k_page_dir]
  2415 00002B81 0F22D9              <1> 	mov	cr3, ecx
  2416                              <1> 	; 20/11/2015
  2417                              <1> 	; Interrupt identification register
  2418 00002B84 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2419                              <1> 	;
  2420 00002B88 3C08                <1> 	cmp 	al, 8 
  2421 00002B8A 7702                <1> 	ja 	short com_i0
  2422                              <1> 	;
  2423                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2424                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2425                              <1> 	; 20/11/2015
  2426                              <1> 	; 17/11/2015
  2427                              <1> 	; 16/11/2015
  2428                              <1> 	; 15/11/2015
  2429                              <1> 	; 24/10/2015
  2430                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2431                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2432                              <1> 	; < serial port 1 interrupt handler >
  2433                              <1> 	;
  2434 00002B8C FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2435                              <1> com_i0:
  2436                              <1> 	;push	eax ; *
  2437                              <1> 	; 07/11/2015
  2438 00002B8E A2[76630000]        <1> 	mov 	byte [ccomport], al
  2439                              <1> 	; 09/11/2015
  2440                              <1> 	;movzx	ebx, ax ; 8 or 9
  2441                              <1> 	; 08/01/2022
  2442 00002B93 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2443                              <1> 	; 17/11/2015
  2444                              <1>  	; reset request for response status
  2445 00002B95 88A3[6C630000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2446                              <1> 	;
  2447                              <1> 	; 20/11/2015
  2448 00002B9B EC                  <1> 	in	al, dx		; read interrupt id. register
  2449 00002B9C EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2450 00002B9E 2404                <1> 	and	al, 4		; received data available?	
  2451 00002BA0 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2452                              <1> 	;
  2453                              <1> 	; 20/11/2015
  2454 00002BA2 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2455 00002BA5 EC                  <1> 	in	al, dx     	; read character
  2456                              <1> 	;JMP	$+2	   	; I/O DELAY
  2457                              <1> 	; 08/11/2015
  2458                              <1> 	; 07/11/2015
  2459 00002BA6 89DE                <1> 	mov	esi, ebx 
  2460 00002BA8 89DF                <1> 	mov	edi, ebx
  2461 00002BAA 81C6[70630000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2462 00002BB0 81C7[72630000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2463 00002BB6 8806                <1> 	mov	[esi], al ; received char (current char)
  2464                              <1> 	; query
  2465 00002BB8 20C0                <1> 	and	al, al
  2466 00002BBA 7527                <1> 	jnz	short com_i2
  2467                              <1>    	; response
  2468                              <1> 	; 17/11/2015
  2469                              <1> 	; set request for response status
  2470 00002BBC FE83[6C630000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2471                              <1> 	;
  2472 00002BC2 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2473 00002BC6 EC                  <1> 	in	al, dx	   	; read line status register 
  2474 00002BC7 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2475 00002BC9 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2476 00002BCB 7445                <1> 	jz	short com_eoi 	; no
  2477 00002BCD B0FF                <1> 	mov 	al, 0FFh   	; response			
  2478 00002BCF 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2479 00002BD3 EE                  <1> 	out	dx, al	   	; send on serial port
  2480                              <1> 	; 17/11/2015
  2481 00002BD4 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2482 00002BD7 7502                <1> 	jne 	short com_i1    ; no
  2483 00002BD9 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2484                              <1> com_i1:
  2485                              <1> 	; 17/11/2015
  2486                              <1> 	; reset request for response status (again)
  2487 00002BDB FE8B[6C630000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2488 00002BE1 EB2F                <1> 	jmp	short com_eoi
  2489                              <1> com_i2:	
  2490                              <1> 	; 08/11/2015
  2491 00002BE3 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2492 00002BE5 7417                <1> 	je	short com_i3	; (check for response signal)
  2493                              <1> 	; 07/11/2015
  2494 00002BE7 3C04                <1> 	cmp	al, 04h	; EOT
  2495 00002BE9 751C                <1> 	jne	short com_i4	
  2496                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2497                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2498                              <1> 	; 08/11/2015
  2499                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2500 00002BEB 861D[36630000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2501 00002BF1 E80BFFFFFF          <1> 	call 	ctrlbrk
  2502 00002BF6 861D[36630000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2503                              <1> 	;mov	al, 04h ; EOT
  2504                              <1> 	; 08/11/2015
  2505 00002BFC EB09                <1> 	jmp	short com_i4	
  2506                              <1> com_i3:
  2507                              <1> 	; 08/11/2015
  2508                              <1> 	; If 0FFh has been received just after a query
  2509                              <1> 	; (schar, ZERO), it is a response signal.
  2510                              <1> 	; 17/11/2015
  2511 00002BFE 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2512 00002C01 7704                <1> 	ja	short com_i4 ; no
  2513                              <1> 	; reset query status (schar)
  2514 00002C03 8807                <1> 	mov	[edi], al ; 0FFh
  2515 00002C05 FEC0                <1> 	inc	al ; 0
  2516                              <1> com_i4:
  2517                              <1> 	; 27/07/2014
  2518                              <1> 	; 09/07/2014
  2519 00002C07 D0E3                <1> 	shl	bl, 1	
  2520 00002C09 81C3[38630000]      <1> 	add	ebx, ttychr
  2521                              <1> 	; 23/07/2014 (always overwrite)
  2522                              <1> 	;;cmp	word [ebx], 0
  2523                              <1> 	;;ja	short com_eoi
  2524                              <1> 	;
  2525 00002C0F 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2526                              <1> 			    ; scan code = 0
  2527                              <1> com_eoi:
  2528                              <1> 	;mov	al, 20h
  2529                              <1> 	;out	20h, al	   ; end of interrupt
  2530                              <1> 	;
  2531                              <1> 	; 07/11/2015
  2532                              <1>       	;pop	eax ; *
  2533 00002C12 A0[76630000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2534                              <1> 	; al = tty number (8 or 9)
  2535 00002C17 E8F31A0000          <1>         call	wakeup
  2536                              <1> com_iret:
  2537                              <1> 	; 23/10/2015
  2538 00002C1C 5A                  <1> 	pop	edx ; **
  2539 00002C1D 59                  <1> 	pop	ecx ; ***
  2540                              <1> 	; 18/11/2015
  2541                              <1> 	;pop	eax ; ****
  2542                              <1> 	;mov	cr3, eax
  2543                              <1> 	;jmp	iiret
  2544 00002C1E E979DDFFFF          <1> 	jmp	iiretp
  2545                              <1> 
  2546                              <1> ;hfgchr:
  2547                              <1> ;	db '0123456789ABCDEF?*'
  2548                              <1> ;	db 0
  2549                              <1> 
  2550                              <1> ;iiretp: ; 01/09/2015
  2551                              <1> ;	; 28/08/2015
  2552                              <1> ;	pop	eax ; (*) page directory
  2553                              <1> ;	mov	cr3, eax
  2554                              <1> ;iiret:
  2555                              <1> ;	; 22/08/2014
  2556                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2557                              <1> ;	out	20h, al	; 8259 PORT
  2558                              <1> ;	;
  2559                              <1> ;	pop	es
  2560                              <1> ;	pop	ds
  2561                              <1> ;	pop	edi
  2562                              <1> ;	pop	esi
  2563                              <1> ;	pop	ebx ; 29/08/2014
  2564                              <1> ;	pop 	eax
  2565                              <1> ;	iretd
  2566                              <1> 
  2567                              <1> sp_init:
  2568                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2569                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2570                              <1> 	; 07/11/2015
  2571                              <1> 	; 29/10/2015
  2572                              <1> 	; 26/10/2015
  2573                              <1> 	; 23/10/2015
  2574                              <1> 	; 29/06/2015
  2575                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2576                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2577                              <1> 	; Initialization of Serial Port Communication Parameters
  2578                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2579                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2580                              <1> 	;
  2581                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2582                              <1> 	;
  2583                              <1> 	; INPUT:  (29/06/2015)
  2584                              <1> 	;	AL = 0 for COM1
  2585                              <1> 	;	     1 for COM2
  2586                              <1> 	;	AH = Communication parameters	
  2587                              <1> 	;
  2588                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2589                              <1> 	;	Bit	4	3	2	1	0
  2590                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2591                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2592                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2593                              <1> 	;		11 = even
  2594                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2595                              <1> 	;		Retro UNIX 386 v1 feature only !
  2596                              <1> 	;	Bit	7    6    5  | Baud rate
  2597                              <1> 	;		------------------------
  2598                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2599                              <1> 	;		0    0    1  | 9600 (12)
  2600                              <1> 	;		0    1    0  | 19200 (6) 
  2601                              <1> 	;		0    1	  1  | 38400 (3) 
  2602                              <1> 	;		1    0	  0  | 14400 (8)
  2603                              <1> 	;		1    0	  1  | 28800 (4)
  2604                              <1> 	;		1    1    0  | 57600 (2)
  2605                              <1> 	;		1    1    1  | 115200 (1) 	
  2606                              <1> 	
  2607                              <1> 	; References:	
  2608                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2609                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2610                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2611                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2612                              <1> 	;
  2613                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2614                              <1> 	;
  2615 00002C23 BB[72630000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2616 00002C28 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2617                              <1> 	; 29/10/2015
  2618 00002C2C 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2619 00002C30 E84F000000          <1> 	call	sp_i3	; call A4	
  2620 00002C35 A880                <1> 	test	al, 80h
  2621 00002C37 740E                <1> 	jz	short sp_i0 ; OK..
  2622                              <1> 		; Error !
  2623                              <1> 	;mov	dx, 3F8h
  2624 00002C39 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2625                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2626                              <1> 	; 08/01/2022
  2627 00002C3C B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2628 00002C3E E841000000          <1> 	call	sp_i3	; call A4	
  2629 00002C43 A880                <1> 	test	al, 80h
  2630 00002C45 7508                <1> 	jnz	short sp_i1
  2631                              <1> sp_i0:
  2632                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2633                              <1>         ; (INT 14h initialization code disables interrupts.)
  2634                              <1> 	;
  2635 00002C47 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2636 00002C4A E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2637                              <1> sp_i1:
  2638 00002C4F 43                  <1> 	inc	ebx
  2639 00002C50 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2640                              <1> 	; 29/10/2015
  2641                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2642                              <1> 	; 08/01/2022
  2643 00002C54 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2644 00002C56 E829000000          <1> 	call	sp_i3	; call A4	
  2645 00002C5B A880                <1> 	test	al, 80h
  2646 00002C5D 740E                <1> 	jz	short sp_i2 ; OK..
  2647                              <1> 		; Error !
  2648                              <1> 	;mov	dx, 2F8h
  2649 00002C5F 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2650                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2651                              <1> 	; 08/01/2022
  2652 00002C62 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2653 00002C64 E81B000000          <1> 	call	sp_i3	; call A4	
  2654 00002C69 A880                <1> 	test	al, 80h
  2655 00002C6B 7516                <1> 	jnz	short sp_i7
  2656                              <1> sp_i2:
  2657 00002C6D C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2658                              <1> sp_i6:
  2659                              <1> 	;; COM2 - enabling IRQ 3
  2660                              <1> 	; 08/01/2022
  2661 00002C70 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2662                              <1> 	; 07/11/2015
  2663                              <1> 	; 26/10/2015
  2664                              <1> 	;pushf
  2665                              <1> 	;cli
  2666                              <1> 	;;
  2667                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2668                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2669                              <1> 	;in	al, dx 	   		; read register
  2670                              <1> 	;JMP	$+2	   		; I/O DELAY
  2671                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2672                              <1> 	;out	dx, al     		; write back to register
  2673                              <1> 	;JMP	$+2	   		; I/O DELAY
  2674                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2675                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2676                              <1> 	;in	al, dx     		; read register
  2677                              <1> 	;JMP	$+2	   		; I/O DELAY
  2678                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2679                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2680                              <1> 	;out	dx, al 	   		; write back to register
  2681                              <1> 	;JMP	$+2        		; I/O DELAY
  2682                              <1> 	;in	al, 21h    		; read interrupt mask register
  2683                              <1> 	;JMP	$+2	   		; I/O DELAY
  2684                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2685                              <1> 	;out	21h, al    		; write back to register
  2686                              <1> 	;
  2687                              <1> 	; 08/01/2022
  2688 00002C72 9C                  <1> 	pushf
  2689 00002C73 E8AA000000          <1> 	call	sp_i8
  2690                              <1> 	; 23/10/2015
  2691 00002C78 B8[572B0000]        <1> 	mov 	eax, com2_int
  2692 00002C7D A3[0B310000]        <1> 	mov	[com2_irq3], eax
  2693                              <1> 	; 26/10/2015
  2694 00002C82 9D                  <1> 	popf	
  2695                              <1> sp_i7:
  2696 00002C83 C3                  <1> 	retn
  2697                              <1> 
  2698                              <1> sp_i3:
  2699                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2700                              <1> 	; 28/10/2015
  2701 00002C84 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2702 00002C86 B000                <1> 	mov	al, 0
  2703 00002C88 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2704 00002C89 EB00                <1> 	JMP	$+2			; I/O DELAY
  2705 00002C8B 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2706 00002C8E B080                <1> 	mov	al, 80h			
  2707 00002C90 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2708                              <1> 	;-----	SET BAUD RATE DIVISOR
  2709                              <1> 	; 26/10/2015
  2710 00002C91 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2711                              <1> 					; of the divisor value
  2712 00002C94 88C8                <1> 	mov	al, cl	; 1
  2713 00002C96 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2714                              <1> 					; 2 = 57600 baud
  2715                              <1> 					; 3 = 38400 baud
  2716                              <1> 					; 6 = 19200 baud
  2717                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2718 00002C97 EB00                <1> 	JMP	$+2			; I/O DELAY
  2719 00002C99 28C0                <1> 	sub	al, al
  2720 00002C9B FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2721                              <1> 					; of the divisor value
  2722 00002C9D EE                  <1> 	out	dx, al ; 0
  2723 00002C9E EB00                <1> 	JMP	$+2			; I/O DELAY
  2724                              <1> 	;	
  2725 00002CA0 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2726                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2727 00002CA2 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2728 00002CA5 EE                  <1> 	out	dx, al			
  2729 00002CA6 EB00                <1> 	JMP	$+2			; I/O DELAY
  2730                              <1> 	; 29/10/2015
  2731 00002CA8 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2732 00002CAA 30C0                <1> 	xor	al, al			; 0
  2733 00002CAC EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2734 00002CAD EB00                <1> 	JMP	$+2	
  2735                              <1> sp_i4:
  2736                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2737                              <1> 	; 29/06/2015 (line status after modem status)
  2738 00002CAF 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2739                              <1> sp_i4s:
  2740 00002CB2 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2741 00002CB3 EB00                <1> 	JMP	$+2			; I/O DELAY
  2742 00002CB5 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2743 00002CB7 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2744                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2745 00002CB9 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2746                              <1> 	; AL = Line status, AH = Modem status
  2747 00002CBA C3                  <1> 	retn
  2748                              <1> 
  2749                              <1> sp_status:
  2750                              <1> 	; 29/06/2015
  2751                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2752                              <1> 	; Get serial port status
  2753 00002CBB 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2754 00002CBF 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2755                              <1> 					; dx = 2FEh for COM2
  2756 00002CC1 EBEF                <1> 	jmp	short sp_i4s
  2757                              <1> 
  2758                              <1> sp_setp: ; Set serial port communication parameters
  2759                              <1> 	; 04/02/2022 
  2760                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2761                              <1> 	; 08/01/2022
  2762                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2763                              <1> 	; 07/11/2015
  2764                              <1> 	; 29/10/2015
  2765                              <1> 	; 29/06/2015
  2766                              <1> 	; Retro UNIX 386 v1 feature only !	
  2767                              <1> 	;
  2768                              <1> 	; INPUT:
  2769                              <1> 	;	AL = 0 for COM1
  2770                              <1> 	;	     1 for COM2
  2771                              <1> 	;	AH = Communication parameters (*)
  2772                              <1> 	; OUTPUT:
  2773                              <1> 	;	CL = Line status
  2774                              <1> 	;	CH = Modem status
  2775                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2776                              <1> 	;		 'invalid parameter !' 
  2777                              <1> 	;		 	 or
  2778                              <1> 	;		 'device not ready !' error
  2779                              <1> 	;	
  2780                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2781                              <1> 	;	Bit	4	3	2	1	0
  2782                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2783                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2784                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2785                              <1> 	;		11 = even
  2786                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2787                              <1> 	;		Retro UNIX 386 v1 feature only !
  2788                              <1> 	;	Bit	7    6    5  | Baud rate
  2789                              <1> 	;		------------------------
  2790                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2791                              <1> 	;		0    0    1  | 9600 (12)
  2792                              <1> 	;		0    1    0  | 19200 (6) 
  2793                              <1> 	;		0    1	  1  | 38400 (3) 
  2794                              <1> 	;		1    0	  0  | 14400 (8)
  2795                              <1> 	;		1    0	  1  | 28800 (4)
  2796                              <1> 	;		1    1    0  | 57600 (2)
  2797                              <1> 	;		1    1    1  | 115200 (1) 
  2798                              <1> 	;
  2799                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2800                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2801                              <1> 	;
  2802                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2803                              <1> 	;
  2804 00002CC3 66BAF803            <1> 	mov	dx, 3F8h
  2805 00002CC7 BB[72630000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2806 00002CCC 3C01                <1> 	cmp	al, 1
  2807 00002CCE 7770                <1> 	ja 	short sp_invp_err
  2808 00002CD0 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2809 00002CD2 FECE                <1> 	dec	dh ; 2F8h
  2810 00002CD4 43                  <1> 	inc	ebx ; COM2 control byte offset
  2811                              <1> sp_setp1:
  2812                              <1> 	; 29/10/2015
  2813 00002CD5 8823                <1> 	mov	[ebx], ah
  2814 00002CD7 0FB6CC              <1> 	movzx 	ecx, ah
  2815 00002CDA C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2816 00002CDD 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2817 00002CE0 8A81[4F2D0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2818 00002CE6 6689C1              <1> 	mov	cx, ax
  2819 00002CE9 E896FFFFFF          <1> 	call	sp_i3
  2820 00002CEE 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2821 00002CF1 A880                <1> 	test	al, 80h
  2822 00002CF3 740F                <1> 	jz	short sp_setp2
  2823 00002CF5 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2824                              <1> stp_dnr_err:
  2825 00002CF8 C705[17670000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2825 00002D00 0000                <1>
  2826                              <1> 	; CL = Line status, CH = Modem status
  2827 00002D02 F9                  <1> 	stc
  2828 00002D03 C3                  <1> 	retn
  2829                              <1> sp_setp2:
  2830 00002D04 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2831                              <1>         ;jna	sp_i6
  2832                              <1> 		      ; COM1 (3F?h)
  2833                              <1> 	; 24/12/2021
  2834 00002D07 7705                <1> 	ja	short sp_i5
  2835 00002D09 E962FFFFFF          <1> 	jmp	sp_i6
  2836                              <1> sp_i5: 
  2837                              <1> 	; 08/01/2022
  2838 00002D0E B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2839                              <1> 	; 07/11/2015
  2840                              <1> 	; 26/10/2015
  2841                              <1> 	; 29/06/2015
  2842                              <1> 	;
  2843                              <1> 	;; COM1 - enabling IRQ 4
  2844                              <1> 	;pushf
  2845                              <1> 	;cli
  2846                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2847                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2848                              <1> 	;in	al, dx 	   		; read register
  2849                              <1> 	;JMP	$+2			; I/O DELAY
  2850                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2851                              <1> 	;out	dx, al     		; write back to register
  2852                              <1> 	;JMP	$+2			; I/O DELAY
  2853                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2854                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2855                              <1> 	;in	al, dx     		; read register
  2856                              <1> 	;JMP	$+2			; I/O DELAY
  2857                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2858                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2859                              <1> 	;out	dx, al 	   		; write back to register
  2860                              <1> 	;JMP	$+2        		; I/O DELAY
  2861                              <1> 	;in	al, 21h    		; read interrupt mask register
  2862                              <1> 	;JMP	$+2			; I/O DELAY
  2863                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2864                              <1> 	;out	21h, al    		; write back to register
  2865                              <1> 	;
  2866                              <1> 	; 08/01/2022
  2867 00002D10 9C                  <1> 	pushf
  2868 00002D11 E80C000000          <1> 	call	sp_i8
  2869                              <1> 	; 23/10/2015
  2870 00002D16 B8[602B0000]        <1> 	mov 	eax, com1_int
  2871 00002D1B A3[07310000]        <1> 	mov	[com1_irq4], eax
  2872                              <1> 	; 26/10/2015
  2873 00002D20 9D                  <1> 	popf
  2874 00002D21 C3                  <1> 	retn
  2875                              <1> 
  2876                              <1> sp_i8:
  2877                              <1> 	; 08/01/2022
  2878                              <1> 	;pushf
  2879 00002D22 FA                  <1> 	cli
  2880                              <1> 	;
  2881                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2882 00002D23 B2FC                <1> 	mov	dl, 0FCh
  2883 00002D25 EC                  <1> 	in	al, dx 	   		; read register
  2884 00002D26 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2885 00002D28 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2886 00002D2A EE                  <1> 	out	dx, al     		; write back to register
  2887 00002D2B EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2888                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2889 00002D2D B2F9                <1> 	mov	dl, 0F9h
  2890 00002D2F EC                  <1> 	in	al, dx     		; read register
  2891 00002D30 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2892                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2893 00002D32 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2894 00002D34 EE                  <1> 	out	dx, al 	   		; write back to register
  2895 00002D35 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2896 00002D37 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2897 00002D39 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2898                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2899 00002D3B 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2900 00002D3D E621                <1> 	out	21h, al    		; write back to register
  2901                              <1> 	;
  2902                              <1> 	;popf	
  2903 00002D3F C3                  <1> 	retn
  2904                              <1> 
  2905                              <1> sp_invp_err:
  2906 00002D40 C705[17670000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2906 00002D48 0000                <1>
  2907 00002D4A 31C9                <1> 	xor	ecx, ecx
  2908 00002D4C 49                  <1> 	dec	ecx ; 0FFFFh
  2909 00002D4D F9                  <1> 	stc
  2910 00002D4E C3                  <1> 	retn
  2911                              <1> 
  2912                              <1> ; 29/10/2015
  2913                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2914 00002D4F 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2915                              <1> 
  2916                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2917                              <1> epoch:
  2918                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2919                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2920                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2921                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2922                              <1> 	; 'epoch' procedure prototype: 
  2923                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2924                              <1> 	; 14/11/2012
  2925                              <1> 	; unixboot.asm (boot file configuration)
  2926                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2927                              <1> 	; 21/7/2012
  2928                              <1> 	; 15/7/2012
  2929                              <1> 	; 14/7/2012		
  2930                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2931                              <1> 	; compute current date and time as UNIX Epoch/Time
  2932                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2933                              <1> 	;
  2934                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2935                              <1> 	;
  2936 00002D56 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2937 00002D5B 86E9                <1>         xchg 	ch,cl
  2938 00002D5D 66890D[76600000]    <1>         mov 	[hour], cx
  2939 00002D64 86F2                <1>         xchg 	dh,dl
  2940 00002D66 668915[78600000]    <1>         mov 	[second], dx
  2941                              <1> 	;
  2942 00002D6D E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2943 00002D72 86E9                <1>         xchg 	ch,cl
  2944 00002D74 66890D[72600000]    <1>         mov 	[year], cx
  2945 00002D7B 86F2                <1>         xchg 	dh,dl
  2946 00002D7D 668915[74600000]    <1>         mov 	[month], dx
  2947                              <1> 	;
  2948 00002D84 66B93030            <1> 	mov 	cx, 3030h
  2949                              <1> 	;
  2950 00002D88 A0[76600000]        <1> 	mov 	al, [hour] ; Hour
  2951                              <1>         	; AL <= BCD number)
  2952 00002D8D D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2953                              <1> 					; AH = AL / 10h
  2954                              <1> 					; AL = AL MOD 10h
  2955 00002D8F D50A                <1>         aad 	; AX= AH*10+AL
  2956 00002D91 A2[76600000]        <1> 	mov 	[hour], al
  2957 00002D96 A0[77600000]        <1> 	mov 	al, [hour+1] ; Minute
  2958                              <1>         	; AL <= BCD number)
  2959 00002D9B D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2960                              <1> 					; AH = AL / 10h
  2961                              <1> 					; AL = AL MOD 10h
  2962 00002D9D D50A                <1>         aad 	; AX= AH*10+AL
  2963 00002D9F A2[77600000]        <1> 	mov 	[minute], al
  2964 00002DA4 A0[78600000]        <1> 	mov 	al, [second] ; Second
  2965                              <1>         	; AL <= BCD number)
  2966 00002DA9 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2967                              <1> 					; AH = AL / 10h
  2968                              <1> 					; AL = AL MOD 10h
  2969 00002DAB D50A                <1>         aad 	; AX= AH*10+AL
  2970 00002DAD A2[78600000]        <1> 	mov 	[second], al
  2971 00002DB2 66A1[72600000]      <1> 	mov 	ax, [year] ; Year (century)
  2972                              <1>  	;push 	ax
  2973                              <1> 	; 08/01/2022
  2974 00002DB8 50                  <1> 	push	eax
  2975                              <1> 	   	; AL <= BCD number)
  2976 00002DB9 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2977                              <1> 					; AH = AL / 10h
  2978                              <1> 					; AL = AL MOD 10h
  2979 00002DBB D50A                <1>         aad 	; AX= AH*10+AL
  2980 00002DBD B464                <1> 	mov 	ah, 100
  2981 00002DBF F6E4                <1> 	mul 	ah
  2982 00002DC1 66A3[72600000]      <1> 	mov 	[year], ax
  2983                              <1> 	;pop	ax
  2984                              <1> 	; 08/01/2022
  2985 00002DC7 58                  <1> 	pop	eax
  2986 00002DC8 88E0                <1> 	mov	al, ah
  2987                              <1>         	; AL <= BCD number)
  2988 00002DCA D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2989                              <1> 					; AH = AL / 10h
  2990                              <1> 					; AL = AL MOD 10h
  2991 00002DCC D50A                <1>         aad 	; AX= AH*10+AL
  2992 00002DCE 660105[72600000]    <1> 	add 	[year], ax
  2993 00002DD5 A0[74600000]        <1> 	mov 	al, [month] ; Month
  2994                              <1>            	; AL <= BCD number)
  2995 00002DDA D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2996                              <1> 					; AH = AL / 10h
  2997                              <1> 					; AL = AL MOD 10h
  2998 00002DDC D50A                <1>         aad 	; AX= AH*10+AL
  2999 00002DDE A2[74600000]        <1> 	mov 	[month], al	
  3000 00002DE3 A0[75600000]        <1>         mov     al, [month+1]      	; Day
  3001                              <1>            	; AL <= BCD number)
  3002 00002DE8 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3003                              <1> 					; AH = AL / 10h
  3004                              <1> 					; AL = AL MOD 10h
  3005 00002DEA D50A                <1>         aad 	; AX= AH*10+AL
  3006 00002DEC A2[75600000]        <1>         mov     [day], al
  3007                              <1> 	
  3008                              <1> convert_to_epoch:
  3009                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3010                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  3011                              <1> 	;
  3012                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3013                              <1> 	;
  3014                              <1> 	; Derived from DALLAS Semiconductor
  3015                              <1> 	; Application Note 31 (DS1602/DS1603)
  3016                              <1> 	; 6 May 1998
  3017 00002DF1 29C0                <1> 	sub 	eax, eax
  3018 00002DF3 66A1[72600000]      <1> 	mov 	ax, [year]
  3019 00002DF9 662DB207            <1> 	sub 	ax, 1970
  3020 00002DFD BA6D010000          <1> 	mov 	edx, 365
  3021 00002E02 F7E2                <1> 	mul 	edx
  3022 00002E04 31DB                <1> 	xor 	ebx, ebx
  3023 00002E06 8A1D[74600000]      <1> 	mov 	bl, [month]
  3024 00002E0C FECB                <1> 	dec 	bl
  3025 00002E0E D0E3                <1> 	shl 	bl, 1
  3026                              <1> 	;sub	edx, edx
  3027 00002E10 668B93[7A600000]    <1> 	mov 	dx, [EBX+DMonth]
  3028 00002E17 8A1D[75600000]      <1>         mov     bl, [day]
  3029 00002E1D FECB                <1> 	dec 	bl
  3030 00002E1F 01D0                <1> 	add 	eax, edx
  3031 00002E21 01D8                <1> 	add 	eax, ebx
  3032                              <1> 			; EAX = days since 1/1/1970
  3033 00002E23 668B15[72600000]    <1> 	mov 	dx, [year]
  3034 00002E2A 6681EAB107          <1> 	sub 	dx, 1969
  3035 00002E2F 66D1EA              <1> 	shr 	dx, 1
  3036 00002E32 66D1EA              <1> 	shr 	dx, 1		
  3037                              <1> 		; (year-1969)/4
  3038 00002E35 01D0                <1> 	add 	eax, edx
  3039                              <1> 			; + leap days since 1/1/1970
  3040 00002E37 803D[74600000]02    <1> 	cmp 	byte [month], 2	; if past february
  3041 00002E3E 7610                <1> 	jna 	short cte1
  3042 00002E40 668B15[72600000]    <1> 	mov 	dx, [year]
  3043 00002E47 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3044 00002E4B 7503                <1> 	jnz 	short cte1		
  3045                              <1> 			; and if leap year
  3046 00002E4D 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3047                              <1> cte1: 			; compute seconds since 1/1/1970
  3048 00002E50 BA18000000          <1> 	mov 	edx, 24
  3049 00002E55 F7E2                <1> 	mul	edx
  3050 00002E57 8A15[76600000]      <1> 	mov 	dl, [hour]
  3051 00002E5D 01D0                <1> 	add 	eax, edx
  3052                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3053                              <1> 	;mov	ebx, 60
  3054 00002E5F B33C                <1> 	mov	bl, 60
  3055 00002E61 F7E3                <1> 	mul	ebx
  3056 00002E63 8A15[77600000]      <1> 	mov 	dl, [minute]
  3057 00002E69 01D0                <1> 	add 	eax, edx
  3058                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3059                              <1> 	;mov 	ebx, 60
  3060 00002E6B F7E3                <1> 	mul	ebx
  3061 00002E6D 8A15[78600000]      <1> 	mov 	dl, [second]
  3062 00002E73 01D0                <1> 	add 	eax, edx
  3063                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3064 00002E75 C3                  <1> 	retn
  3065                              <1> 
  3066                              <1> get_rtc_time:
  3067                              <1> 	; 15/03/2015
  3068                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3069                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3070                              <1> 	; INT 1Ah						:
  3071                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3072                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3073                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3074                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3075                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3076                              <1> 	;								
  3077                              <1> RTC_20: 			; GET RTC TIME
  3078 00002E76 FA                  <1> 	cli
  3079 00002E77 E8BEDCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3080 00002E7C 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3081                              <1> 
  3082 00002E7E B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3083 00002E80 E89DDCFFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3084 00002E85 88C6                <1> 	MOV	DH,AL		; SAVE
  3085 00002E87 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3086 00002E89 E894DCFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3087 00002E8E 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3088 00002E90 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3089 00002E92 B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3090 00002E94 E889DCFFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3091 00002E99 88C1                <1> 	MOV	CL,AL		; SAVE
  3092 00002E9B B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3093 00002E9D E880DCFFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3094 00002EA2 88C5                <1> 	MOV	CH,AL		; SAVE
  3095 00002EA4 F8                  <1> 	CLC			; SET CY= 0
  3096                              <1> RTC_29:
  3097 00002EA5 FB                  <1> 	sti
  3098 00002EA6 C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3099                              <1> 
  3100                              <1> get_rtc_date:
  3101                              <1> 	; 15/03/2015
  3102                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3103                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3104                              <1> 	; INT 1Ah						       :
  3105                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3106                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3107                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3108                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3109                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3110                              <1> 	;
  3111                              <1> RTC_40: 			; GET RTC DATE
  3112 00002EA7 FA                  <1> 	cli
  3113 00002EA8 E88DDCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3114 00002EAD 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3115                              <1> 
  3116 00002EAF B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3117 00002EB1 E86CDCFFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3118 00002EB6 88C2                <1> 	MOV	DL,AL		; SAVE
  3119 00002EB8 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3120 00002EBA E863DCFFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3121 00002EBF 88C6                <1> 	MOV	DH,AL		; SAVE
  3122 00002EC1 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3123 00002EC3 E85ADCFFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3124 00002EC8 88C1                <1> 	MOV	CL,AL		; SAVE
  3125 00002ECA B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3126 00002ECC E851DCFFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3127 00002ED1 88C5                <1> 	MOV	CH,AL		; SAVE
  3128 00002ED3 F8                  <1> 	CLC			; SET CY=0
  3129                              <1> RTC_49:
  3130 00002ED4 FB                  <1> 	sti
  3131 00002ED5 C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3132                              <1> 
  3133                              <1> set_date_time:
  3134                              <1> convert_from_epoch:
  3135                              <1> 	; 02/06/2022
  3136                              <1> 	; 01/06/2022 (BugFix)
  3137                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3138                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3139                              <1> 	; 'convert_from_epoch' procedure prototype:
  3140                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3141                              <1> 	;
  3142                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))
  3143                              <1> 	;
  3144                              <1> 	; Derived from DALLAS Semiconductor
  3145                              <1> 	; Application Note 31 (DS1602/DS1603)
  3146                              <1> 	; 6 May 1998
  3147                              <1> 	;
  3148                              <1> 	; INPUT:
  3149                              <1> 	; EAX = Unix (Epoch) Time
  3150                              <1> 	;
  3151 00002ED6 31D2                <1> 	xor 	edx, edx
  3152                              <1> 	; 02/06/2022
  3153 00002ED8 31C9                <1> 	xor	ecx, ecx
  3154 00002EDA 31DB                <1> 	xor	ebx, ebx
  3155                              <1> 	;mov 	ecx, 60
  3156 00002EDC B13C                <1> 	mov	cl, 60
  3157 00002EDE F7F1                <1> 	div	ecx
  3158                              <1> 	;mov 	[imin], eax  ; whole minutes
  3159                              <1> 			     ; since 1/1/1970
  3160                              <1> 	;mov 	[second], dx ; leftover seconds
  3161 00002EE0 8815[78600000]      <1> 	mov	[second], dl ; 02/06/2022
  3162 00002EE6 29D2                <1> 	sub 	edx, edx
  3163 00002EE8 F7F1                <1> 	div	ecx
  3164                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3165                              <1> 	;		     ; since 1/1/1970
  3166                              <1> 	;mov 	[minute], dx ; leftover minutes
  3167 00002EEA 8815[77600000]      <1> 	mov	[minute], dl ; 02/06/2022
  3168 00002EF0 31D2                <1> 	xor	edx, edx
  3169                              <1> 	;mov 	cx, 24
  3170 00002EF2 B118                <1> 	mov 	cl, 24
  3171 00002EF4 F7F1                <1> 	div	ecx
  3172                              <1> 	;mov 	[iday], ax   ; whole days
  3173                              <1> 			     ; since 1/1/1970
  3174                              <1> 	;mov 	[hour], dx   ; leftover hours
  3175 00002EF6 8815[76600000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3176                              <1> 
  3177 00002EFC 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3178                              <1> 			     ; 1/1/1968 	
  3179                              <1> 	;mov 	[iday], ax
  3180 00002F01 50                  <1> 	push 	eax
  3181 00002F02 29D2                <1> 	sub	edx, edx
  3182 00002F04 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3183 00002F09 F7F1                <1> 	div	ecx
  3184 00002F0B 59                  <1> 	pop 	ecx
  3185                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3186                              <1> 	;push	dx
  3187                              <1> 	; 01/06/2022
  3188 00002F0C 52                  <1> 	push 	edx
  3189                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3190 00002F0D 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3191 00002F11 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3192 00002F12 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3193                              <1> 	;mov 	[lday], ax   ; since 1968
  3194                              <1> 	;mov 	cx, [iday]
  3195 00002F15 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday
  3196 00002F16 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3197 00002F18 B96D010000          <1> 	mov 	ecx, 365
  3198 00002F1D 31D2                <1> 	xor	edx, edx
  3199                              <1> 	; EAX = iday-lday, EDX = 0
  3200 00002F1F F7F1                <1> 	div	ecx
  3201                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3202                              <1> 	;jday = iday - (iyrs*365) - lday
  3203                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3204                              <1> 	;add	eax, 1968
  3205 00002F21 6605B007            <1> 	add 	ax, 1968     ; compute year
  3206 00002F25 66A3[72600000]      <1> 	mov 	[year], ax
  3207                              <1> 	;mov 	cx, dx
  3208                              <1> 	; 02/06/2022
  3209 00002F2B 89D1                <1> 	mov	ecx, edx
  3210                              <1> 	;mov 	dx, [qday]
  3211                              <1> 	;pop	dx
  3212                              <1> 	; 01/06/2022
  3213 00002F2D 5A                  <1> 	pop 	edx
  3214 00002F2E 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3215 00002F33 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3216 00002F35 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3217 00002F39 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3218 00002F3A 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3219                              <1> cfe1:			
  3220                              <1> 	;mov 	[jday], cx
  3221                              <1> 	;mov 	bx, 12       ; estimate month
  3222                              <1> 	;sub	ebx, ebx
  3223                              <1> 	; 02/06/2022
  3224 00002F3E B30C                <1> 	mov	bl, 12
  3225 00002F40 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3226 00002F44 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3227                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3228                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3229                              <1> 	; 02/06/2022
  3230 00002F48 39D1                <1> 	cmp	ecx, edx 	 		
  3231 00002F4A 7319                <1> 	jnb 	short cfe3
  3232                              <1> 	;dec 	bx           ; month = month - 1
  3233 00002F4C FECB                <1> 	dec	bl			
  3234                              <1> 	;shl 	bx, 1
  3235 00002F4E D0E3                <1> 	shl	bl, 1
  3236 00002F50 668B93[7A600000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3237                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3238                              <1> 	; 02/06/2022
  3239 00002F57 D0EB                <1> 	shr	bl, 1
  3240 00002F59 80FB01              <1> 	cmp	bl, 1
  3241                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0
  3242 00002F5C 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3243 00002F5E 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3244 00002F60 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3245                              <1> 	;inc 	dx           ; mday = mday + 1
  3246 00002F62 42                  <1> 	inc	edx
  3247 00002F63 EBE3                <1> 	jmp 	short cfe2
  3248                              <1> cfe3:
  3249                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3250                              <1> 	; 02/06/2022
  3251 00002F65 FEC3                <1> 	inc	bl
  3252                              <1> 	;mov 	[month], bx
  3253 00002F67 881D[74600000]      <1> 	mov	[month], bl
  3254                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1
  3255 00002F6D 29D1                <1> 	sub	ecx, edx
  3256                              <1> 	;inc 	cx
  3257 00002F6F FEC1                <1> 	inc	cl
  3258                              <1> 	;mov 	[day], cx
  3259 00002F71 880D[75600000]      <1> 	mov	[day], cl    ; 02/06/2022
  3260                              <1> 	
  3261                              <1> 	; eax, ebx, ecx, edx is changed at return
  3262                              <1> 	; output ->
  3263                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3264                              <1> 	
  3265                              <1> 	; 01/06/2022 (BugFix)
  3266                              <1> _set_date:
  3267 00002F77 66A1[72600000]      <1> 	mov	ax, [year]
  3268 00002F7D B520                <1> 	mov	ch, 20h ; century (bcd)
  3269 00002F7F 662DD007            <1> 	sub	ax, 2000
  3270 00002F83 7306                <1> 	jnc	short set_date
  3271 00002F85 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3272 00002F87 6683C064            <1> 	add	ax, 100	
  3273                              <1> 	; 01/06/2022
  3274                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3275                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3276                              <1> set_date:
  3277                              <1>         ;mov	al, [year+1]
  3278                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3279                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3280                              <1> 	;		     ; AL = AH * 10h + AL
  3281                              <1> 	;mov 	ch, al ; century (BCD)
  3282                              <1> 	;mov 	al, [year]
  3283                              <1> 	; al = year (0-99) ; 01/06/2022
  3284 00002F8B D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3285 00002F8D D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3286                              <1> 			     ; AL = AH * 10h + AL
  3287 00002F8F 88C1                <1> 	mov 	cl, al ; year (BCD)
  3288 00002F91 A0[74600000]        <1>         mov 	al, [month]
  3289 00002F96 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3290 00002F98 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3291                              <1> 			     ; AL = AH * 10h + AL
  3292 00002F9A 88C6                <1> 	mov 	dh, al ; month (BCD)
  3293 00002F9C A0[75600000]        <1> 	mov 	al, [day]
  3294 00002FA1 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3295 00002FA3 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3296                              <1> 			     ; AL = AH * 10h + AL
  3297                              <1> 	; 01/06/2022 (BugFix)
  3298 00002FA5 88C2                <1> 	mov 	dl, al ; day (BCD)
  3299                              <1> 
  3300                              <1> 	; Set real-time clock date
  3301 00002FA7 E879000000          <1> 	call	set_rtc_date
  3302                              <1> set_time:
  3303                              <1>         ; Read real-time clock time 
  3304                              <1> 	; (get day light saving time bit status)
  3305 00002FAC FA                  <1>  	cli
  3306 00002FAD E888DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3307                              <1> 	; cf = 1 -> al = 0
  3308 00002FB2 7207                <1>         jc      short stime1
  3309 00002FB4 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3310 00002FB6 E867DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3311                              <1> stime1:
  3312 00002FBB FB                  <1> 	sti
  3313 00002FBC 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3314 00002FBE 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3315                              <1> 	; DL = 1 or 0 (day light saving time)
  3316                              <1> 	;	
  3317 00002FC0 A0[76600000]        <1> 	mov 	al, [hour]
  3318 00002FC5 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3319 00002FC7 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3320                              <1> 			     ; AL = AH * 10h + AL
  3321 00002FC9 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3322 00002FCB A0[77600000]        <1>         mov     al, [minute]
  3323 00002FD0 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3324 00002FD2 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3325                              <1> 			     ; AL = AH * 10h + AL
  3326 00002FD4 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3327 00002FD6 A0[78600000]        <1>         mov     al, [second]
  3328 00002FDB D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3329 00002FDD D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3330                              <1> 			     ; AL = AH * 10h + AL
  3331 00002FDF 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3332                              <1> 
  3333                              <1> 	; Set real-time clock time
  3334                              <1>  	; call	set_rtc_time
  3335                              <1> set_rtc_time:
  3336                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3337                              <1> 	; 15/03/2015							  :
  3338                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3339                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3340                              <1> 	; INT 1Ah							  :
  3341                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3342                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3343                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3344                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3345                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3346                              <1> 	;								  :
  3347                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3348                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3349                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3350                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3351                              <1> 	;								  :
  3352                              <1> RTC_30: 			; SET RTC TIME
  3353 00002FE1 FA                  <1> 	cli
  3354 00002FE2 E853DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3355 00002FE7 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3356 00002FE9 E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3357                              <1> RTC_35:
  3358 00002FEE 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3359 00002FF0 B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3360 00002FF2 E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3361 00002FF7 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3362 00002FF9 B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3363 00002FFB E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3364 00003000 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3365 00003002 B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3366 00003004 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3367                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3368 00003009 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3369 0000300D E810DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3370 00003012 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3371 00003014 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3372 00003016 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3373 00003019 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3374 0000301B 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3375 0000301D E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3376 00003022 F8                  <1> 	CLC			; SET CY= 0
  3377 00003023 FB                  <1> 	sti
  3378 00003024 C3                  <1> 	RETn			; RETURN WITH CY= 0
  3379                              <1> 
  3380                              <1> set_rtc_date:
  3381                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)	   :
  3382                              <1> 	; 15/03/2015						   :
  3383                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	   :
  3384                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	   :
  3385                              <1> 	; INT 1Ah						   :
  3386                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3387                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3388                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3389                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3390                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3391                              <1> 	;							   :
  3392                              <1> RTC_50: 			; SET RTC DATE
  3393 00003025 FA                  <1> 	cli
  3394 00003026 E80FDBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3395 0000302B 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3396 0000302D E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3397                              <1> RTC_55:
  3398 00003032 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3399 00003036 E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3400 0000303B 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3401 0000303D B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3402 0000303F E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3403 00003044 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3404 00003046 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3405 00003048 E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3406 0000304D 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3407 0000304F B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3408 00003051 E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3409 00003056 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3410 00003058 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3411 0000305A E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3412                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3413 0000305F 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3414 00003063 E8BADAFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3415 00003068 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3416 0000306A 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3417 0000306C E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3418 00003071 F8                  <1> 	CLC			; SET CY= 0
  3419 00003072 FB                  <1> 	sti
  3420 00003073 C3                  <1> 	RETn			; RETURN CY=0
  3421                              <1> 
  3422                              <1> 	; 15/03/2015
  3423                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3424 00003074 B426                <1> 	mov	ah, 26h
  3425 00003076 B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3426 00003078 E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3427 0000307D B482                <1> 	mov	ah, 82h
  3428 0000307F B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3429 00003081 E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3430 00003086 B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3431 00003088 E895DAFFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3432 0000308D B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3433                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3434                              <1> 	;RETn
  3435                              <1> 	; 12/02/2022
  3436 0000308F E98EDAFFFF          <1> 	jmp	CMOS_READ
  3437                              <1> 
  3438                              <1> 	; 15/03/2015
  3439                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3440                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3441 00003094 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3442                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3443 00003095 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3444 00003097 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3445 00003098 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3446 0000309A FA                  <1> 	cli			; DISABLE INTERRUPTS
  3447 0000309B E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3448 0000309D 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3449 0000309F E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3450 000030A1 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3451 000030A3 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3452 000030A5 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3453 000030A7 90                  <1> 	nop			; I/O DELAY
  3454 000030A8 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3455                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3456 000030AA 9D                  <1> 	popf	
  3457 000030AB C3                  <1> 	RETn
  3458                              <1> 
  3459                              <1> bf_init:
  3460                              <1> 	; 14/08/2015
  3461                              <1> 	; 02/07/2015
  3462                              <1> 	; 01/07/2015
  3463                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3464                              <1> 	; Buffer (pointer) initialization !
  3465                              <1> 	; 
  3466                              <1> 	; 17/07/2013 - 24/07/2013
  3467                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3468                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3469                              <1> 	;
  3470 000030AC BF[88660000]        <1> 	mov	edi, bufp 
  3471 000030B1 B8[78730000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3472 000030B6 29D2                <1> 	sub	edx, edx
  3473 000030B8 FECA                <1> 	dec	dl
  3474 000030BA 31C9                <1> 	xor	ecx, ecx
  3475 000030BC 49                  <1> 	dec	ecx
  3476                              <1> bi0:
  3477 000030BD 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3478 000030C2 AB                  <1> 	stosd
  3479 000030C3 89C6                <1> 	mov	esi, eax
  3480 000030C5 8916                <1> 	mov	[esi], edx ; 000000FFh
  3481                              <1> 			    ; Not a valid device sign
  3482 000030C7 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3483                              <1> 		      ; Not a valid block number sign 	 	
  3484 000030CA 3D[48670000]        <1> 	cmp	eax, buffer
  3485 000030CF 77EC                <1> 	ja	short bi0
  3486 000030D1 B8[78730000]        <1> 	mov	eax, sb0
  3487 000030D6 AB                  <1> 	stosd
  3488 000030D7 B8[80750000]        <1> 	mov	eax, sb1
  3489 000030DC AB                  <1> 	stosd
  3490 000030DD 89C6                <1> 	mov	esi, eax ; offset sb1
  3491 000030DF 8916                <1> 	mov	[esi], edx ; 000000FFh
  3492                              <1> 			    ; Not a valid device sign
  3493 000030E1 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3494                              <1> 		      ; Not a valid block number sign 	 
  3495                              <1> 	; 14/08/2015
  3496                              <1> 	;call 	rdev_init
  3497                              <1> 	;retn
  3498                              <1> 
  3499                              <1> rdev_init: ; root device, super block buffer initialization
  3500                              <1> 	; 01/02/2022
  3501                              <1> 	; 14/08/2015
  3502                              <1> 	; Retro UNIX 386 v1 feature only !
  3503                              <1> 	;
  3504                              <1> 	; NOTE: Disk partitions (file systems), logical
  3505                              <1> 	; drive initialization, partition's start sector etc.
  3506                              <1> 	; will be coded here, later in 'ldrv_init'	
  3507                              <1> 
  3508 000030E4 0FB605[285E0000]    <1> 	movzx	eax, byte [boot_drv]
  3509                              <1> rdi_0:
  3510 000030EB 3C80                <1> 	cmp	al, 80h
  3511 000030ED 7202                <1> 	jb	short rdi_1
  3512 000030EF 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3513                              <1> rdi_1:
  3514 000030F1 A2[AE660000]        <1> 	mov	[rdev], al
  3515 000030F6 BB[78730000]        <1>         mov	ebx, sb0 ; super block buffer
  3516 000030FB 8903                <1> 	mov 	[ebx], eax
  3517 000030FD B001                <1> 	mov	al, 1 ; eax = 1
  3518 000030FF 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3519                              <1> 	;call 	diskio
  3520                              <1> 	;retn
  3521                              <1> 	; 01/02/2022
  3522 00003102 E9C1250000          <1> 	jmp	diskio
  3523                              <1> 
  3524                              <1> ; 23/10/2015
  3525                              <1> com1_irq4:
  3526 00003107 [0F310000]          <1> 	dd dummy_retn
  3527                              <1> com2_irq3:
  3528 0000310B [0F310000]          <1> 	dd dummy_retn
  3529                              <1> 
  3530                              <1> dummy_retn:
  3531 0000310F C3                  <1> 	retn
  2049                                  %include 'u1.s'        ; 10/05/2015
  2050                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2051                              <1> ; Last Modification: 27/02/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 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2062                              <1> ;
  2063                              <1> ; ****************************************************************************
  2064                              <1> ; 23/11/2015
  2065                              <1> 
  2066                              <1> unkni: ; / used for all system calls
  2067                              <1> sysent: ; < enter to system call >
  2068                              <1> 	; 27/02/2022
  2069                              <1> 	; 01/02/2022
  2070                              <1> 	; 19/10/2015
  2071                              <1> 	; 21/09/2015
  2072                              <1> 	; 01/07/2015
  2073                              <1> 	; 19/05/2015
  2074                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2075                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2076                              <1> 	;
  2077                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2078                              <1> 	; The trap type is determined and an indirect jump is made to 
  2079                              <1> 	; the appropriate system call handler. If there is a trap inside
  2080                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2081                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2082                              <1> 	; instructor is decoded to get the the system code part (see
  2083                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2084                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2085                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2086                              <1> 	; is called. If the call is legitimate control passes to the
  2087                              <1> 	; appropriate system routine.
  2088                              <1> 	;
  2089                              <1> 	; Calling sequence:
  2090                              <1> 	;	Through a trap caused by any sys call outside the system.
  2091                              <1> 	; Arguments:
  2092                              <1> 	;	Arguments of particular system call.	
  2093                              <1> 	; ...............................................................
  2094                              <1> 	;	
  2095                              <1> 	; Retro UNIX 8086 v1 modification: 
  2096                              <1> 	;       System call number is in EAX register.
  2097                              <1> 	;
  2098                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2099                              <1> 	;	registers depending of function details.
  2100                              <1>   	;
  2101                              <1> 	; 16/04/2015
  2102 00003110 368925[C0660000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2103                              <1> 	; save user registers
  2104 00003117 1E                  <1> 	push	ds
  2105 00003118 06                  <1> 	push	es
  2106 00003119 0FA0                <1> 	push	fs
  2107 0000311B 0FA8                <1> 	push	gs
  2108 0000311D 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2109                              <1> 	;
  2110                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2111                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2112                              <1> 	;	for saving/restoring user registers.)
  2113                              <1> 	;
  2114 0000311E 50                  <1> 	push	eax ; 01/07/2015
  2115 0000311F 66B81000            <1> 	mov     ax, KDATA
  2116 00003123 8ED8                <1>         mov     ds, ax
  2117 00003125 8EC0                <1>         mov     es, ax
  2118 00003127 8EE0                <1>         mov     fs, ax
  2119 00003129 8EE8                <1>         mov     gs, ax
  2120 0000312B A1[08630000]        <1> 	mov	eax, [k_page_dir]
  2121 00003130 0F22D8              <1> 	mov	cr3, eax
  2122 00003133 58                  <1> 	pop	eax ; 01/07/2015
  2123                              <1> 	; 19/10/2015
  2124 00003134 FC                  <1> 	cld
  2125                              <1> 	;
  2126 00003135 FE05[BF660000]      <1> 	inc	byte [sysflg]
  2127                              <1> 		; incb sysflg / indicate a system routine is in progress
  2128 0000313B FB                  <1>         sti 	; 18/01/2014
  2129                              <1> 	;jnz	panic ; 24/05/2013
  2130                              <1> 		; beq 1f
  2131                              <1> 		; jmp panic ; / called if trap inside system
  2132                              <1> 	; 01/02/2022
  2133 0000313C 7405                <1> 	jz	short sysent_1
  2134 0000313E E984F9FFFF          <1> 	jmp	panic
  2135                              <1> sysent_1:
  2136                              <1> ;1:	; 16/04/2015
  2137 00003143 A3[C8660000]        <1> 	mov	[u.r0], eax
  2138 00003148 8925[C4660000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2139                              <1> 	;
  2140                              <1> 		; mov $s.syst+2,clockp
  2141                              <1> 		; mov r0,-(sp) / save user registers 
  2142                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2143                              <1> 			   ; / in u.r0
  2144                              <1> 		; mov r1,-(sp)
  2145                              <1> 		; mov r2,-(sp)
  2146                              <1> 		; mov r3,-(sp)
  2147                              <1> 		; mov r4,-(sp)
  2148                              <1> 		; mov r5,-(sp)
  2149                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2150                              <1> 		             ; / arithmetic unit
  2151                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2152                              <1> 		             ; / extended arithmetic unit
  2153                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2154                              <1> 		             ; / arithmetic unit
  2155                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2156                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2157                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2158                              <1> 		; sub $sys,r0 / get xxx code
  2159 0000314E C1E002              <1> 	shl	eax, 2
  2160                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2161 00003151 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2162                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2163                              <1> 	;jnb	short badsys
  2164                              <1> 		; bhis badsys / yes, bad system call
  2165                              <1> 	; 27/02/2022
  2166 00003156 7205                <1> 	jb	short _2
  2167 00003158 E954010000          <1> 	jmp	badsys
  2168                              <1> _2:
  2169                              <1> 	; 27/02/2022
  2170                              <1> 	;cmc
  2171                              <1> 	;pushf	
  2172                              <1> 	;push	eax
  2173 0000315D 8B2D[C0660000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2174                              <1> 	;mov	al, 0FEh ; 11111110b
  2175                              <1> 	;;adc	al, 0 ; al = al + cf
  2176                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2177 00003163 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2178                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2179                              <1> 				 ; / and clear carry bit
  2180                              <1> 	;pop	ebp ; eax
  2181 00003167 89C5                <1> 	mov	ebp, eax
  2182                              <1> 	;popf
  2183                              <1>         ;;jc	badsys
  2184                              <1> 	; 27/02/2022
  2185                              <1> 	;jnc	short _3
  2186                              <1> 	;jmp	badsys
  2187                              <1> ;_3:
  2188 00003169 A1[C8660000]        <1> 	mov	eax, [u.r0]
  2189                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2190 0000316E FFA5[74310000]      <1> 	jmp	dword [ebp+syscalls]
  2191                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2192                              <1> 		            ; / to proper system routine.
  2193                              <1> syscalls: ; 1:
  2194                              <1> 	; 21/09/2015
  2195                              <1> 	; 01/07/2015
  2196                              <1> 	; 16/04/2015 (32 bit address modification) 
  2197 00003174 [7B320000]          <1> 	dd sysrele	; / 0
  2198 00003178 [23330000]          <1> 	dd sysexit 	; / 1
  2199 0000317C [4E340000]          <1> 	dd sysfork 	; / 2
  2200 00003180 [54350000]          <1> 	dd sysread 	; / 3
  2201 00003184 [67350000]          <1> 	dd syswrite 	; / 4
  2202 00003188 [D0350000]          <1> 	dd sysopen 	; / 5
  2203 0000318C [FF360000]          <1> 	dd sysclose 	; / 6
  2204 00003190 [C9330000]          <1> 	dd syswait 	; / 7
  2205 00003194 [7C360000]          <1> 	dd syscreat 	; / 8
  2206 00003198 [B13A0000]          <1> 	dd syslink 	; / 9
  2207 0000319C [6D3B0000]          <1> 	dd sysunlink 	; / 10
  2208 000031A0 [343C0000]          <1> 	dd sysexec 	; / 11
  2209 000031A4 [BD420000]          <1> 	dd syschdir 	; / 12
  2210 000031A8 [A2430000]          <1> 	dd systime 	; / 13
  2211 000031AC [B8360000]          <1> 	dd sysmkdir 	; / 14
  2212 000031B0 [0F430000]          <1> 	dd syschmod 	; / 15
  2213 000031B4 [72430000]          <1> 	dd syschown 	; / 16
  2214 000031B8 [D5430000]          <1> 	dd sysbreak 	; / 17
  2215 000031BC [F53F0000]          <1> 	dd sysstat 	; / 18
  2216 000031C0 [A5440000]          <1> 	dd sysseek 	; / 19
  2217 000031C4 [B7440000]          <1> 	dd systell 	; / 20
  2218 000031C8 [EB4F0000]          <1> 	dd sysmount 	; / 21
  2219 000031CC [D6500000]          <1> 	dd sysumount 	; / 22
  2220 000031D0 [33450000]          <1> 	dd syssetuid 	; / 23
  2221 000031D4 [64450000]          <1> 	dd sysgetuid 	; / 24
  2222 000031D8 [B1430000]          <1> 	dd sysstime 	; / 25
  2223 000031DC [27450000]          <1> 	dd sysquit 	; / 26
  2224 000031E0 [1B450000]          <1> 	dd sysintr 	; / 27
  2225 000031E4 [D23F0000]          <1> 	dd sysfstat 	; / 28
  2226 000031E8 [17370000]          <1> 	dd sysemt 	; / 29
  2227 000031EC [5F370000]          <1> 	dd sysmdate 	; / 30
  2228 000031F0 [B9370000]          <1> 	dd sysstty 	; / 31
  2229 000031F4 [A4390000]          <1> 	dd sysgtty 	; / 32
  2230 000031F8 [5A370000]          <1> 	dd sysilgins 	; / 33
  2231 000031FC [EA580000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2232                              <1> 			     ; 11/06/2014
  2233 00003200 [01590000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2234                              <1> 			     ; 01/07/2015
  2235 00003204 [D9590000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2236                              <1> 			     ; 21/09/2015 - get last error number
  2237                              <1> end_of_syscalls:
  2238                              <1> 
  2239                              <1> error:
  2240                              <1> 	; 17/09/2015
  2241                              <1> 	; 03/09/2015
  2242                              <1> 	; 01/09/2015
  2243                              <1> 	; 09/06/2015
  2244                              <1> 	; 13/05/2015
  2245                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2246                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2247                              <1> 	;
  2248                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2249                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2250                              <1> 	;
  2251                              <1> 	; INPUTS -> none
  2252                              <1> 	; OUTPUTS ->
  2253                              <1> 	;	processor status - carry (c) bit is set (means error)
  2254                              <1> 	;
  2255                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2256                              <1> 	; 	      Because, jumps to error procedure
  2257                              <1> 	;	      disrupts push-pop nesting balance)
  2258                              <1> 	;
  2259 00003208 8B2D[C0660000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2260 0000320E 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2261                              <1> 				 ; (system call will return with cf = 1)
  2262                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2263                              <1> 		               ; / users stack
  2264                              <1> 	; 17/09/2015
  2265 00003212 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2266                              <1> 				 ; for saving/restoring user registers	
  2267                              <1> 	;cmp	ebp, [u.usp]
  2268                              <1> 	;je	short err0	
  2269 00003215 892D[C4660000]      <1> 	mov	[u.usp], ebp
  2270                              <1> ;err0:
  2271                              <1> 	; 01/09/2015
  2272 0000321B 8B25[C4660000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2273                              <1> 				    ; 10/04/2013
  2274                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2275                              <1> 				    ; related procedures will jump to 'error'
  2276                              <1> 				    ; procedure directly without returning to 
  2277                              <1> 				    ; the caller procedure. So, stack pointer
  2278                              <1>                                     ; must be restored here.)
  2279                              <1> 	; 13/05/2015
  2280                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2281                              <1> 	;	'get last error' system call later. 	
  2282                              <1> 
  2283                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2284 00003221 C605[29670000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2285                              <1> 
  2286                              <1> sysret: ; < return from system call>
  2287                              <1> 	; 01/02/2022
  2288                              <1> 	; 10/09/2015
  2289                              <1> 	; 29/07/2015
  2290                              <1> 	; 25/06/2015
  2291                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2292                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2293                              <1> 	;
  2294                              <1> 	; 'sysret' first checks to see if process is about to be 
  2295                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2296                              <1> 	; If not, following happens:	 
  2297                              <1> 	; 	1) The user's stack pointer is restored.
  2298                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2299                              <1> 	;	   i-node has been modified. If it has, it is written out
  2300                              <1> 	;	   via 'ppoke'.
  2301                              <1> 	;	3) If the super block has been modified, it is written out
  2302                              <1> 	;	   via 'ppoke'.				
  2303                              <1> 	;	4) If the dismountable file system's super block has been
  2304                              <1> 	;	   modified, it is written out to the specified device
  2305                              <1> 	;	   via 'ppoke'.
  2306                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2307                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2308                              <1> 	;	   another user a chance to run.
  2309                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2310                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2311                              <1> 	;
  2312                              <1> 	; Calling sequence:
  2313                              <1> 	;	jump table or 'br sysret'
  2314                              <1> 	; Arguments: 
  2315                              <1> 	;	-	
  2316                              <1> 	; ...............................................................
  2317                              <1> 	;	
  2318                              <1> 	; ((AX=r1 for 'iget' input))
  2319                              <1> 	;	
  2320                              <1> 	;xor	ax, ax ; 04/05/2013
  2321                              <1> 	; 01/02/2022
  2322 00003228 31C0                <1> 	xor	eax, eax
  2323                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2324 0000322A FEC0                <1> 	inc	al ; 04/05/2013
  2325 0000322C 3805[10670000]      <1> 	cmp	[u.bsys], al ; 1
  2326                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2327                              <1>         ;jnb	sysexit ; 04/05/2013
  2328                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2329                              <1> 	; 01/02/2022
  2330 00003232 7205                <1> 	jb	short sysret_2
  2331 00003234 E9EA000000          <1> 	jmp	sysexit
  2332                              <1> sysret_2:
  2333                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2334                              <1> 		; mov u.sp,sp / no point stack to users stack
  2335 00003239 FEC8                <1> 	dec 	al ; mov ax, 0
  2336                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2337 0000323B E8DE160000          <1> 	call	iget
  2338                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2339                              <1> 		            ; / it is written out
  2340 00003240 6631C0              <1> 	xor 	ax, ax ; 0
  2341 00003243 3805[BD660000]      <1> 	cmp	[smod], al ; 0
  2342                              <1> 		; tstb	smod / has the super block been modified
  2343 00003249 7614                <1> 	jna	short sysret1
  2344                              <1> 		; beq	1f / no, 1f
  2345 0000324B A2[BD660000]        <1> 	mov	[smod], al ; 0
  2346                              <1> 		; clrb smod / yes, clear smod
  2347 00003250 BB[78730000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2348 00003255 66810B0002          <1>    	or	word [ebx], 200h ;;
  2349                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2350                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2351                              <1> 		      	      ; / output
  2352                              <1> 	; AX = 0
  2353 0000325A E851230000          <1> 	call 	poke ; 07/08/2013
  2354                              <1> 	;call	ppoke
  2355                              <1> 	; AX = 0
  2356                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2357                              <1> sysret1: ;1:
  2358 0000325F 3805[BE660000]      <1> 	cmp	[mmod], al ; 0
  2359                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2360                              <1> 		           ; / system
  2361 00003265 7614                <1> 	jna	short sysrel0
  2362                              <1> 		; beq 1f / been modified?  no, 1f
  2363 00003267 A2[BE660000]        <1> 	mov	[mmod], al ; 0	
  2364                              <1> 		; clrb	mmod / yes, clear mmod
  2365                              <1>         ;mov    ax, [mntd]
  2366                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2367 0000326C BB[80750000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2368                              <1>         ;;mov	[ebx], al
  2369                              <1> 	;mov    [sb1], al
  2370                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2371 00003271 66810B0002          <1> 	or	word [ebx], 200h
  2372                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2373                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2374 00003276 E835230000          <1> 	call	poke ; 07/08/2013
  2375                              <1> 	;call	ppoke 
  2376                              <1> 		; jsr r0,ppoke / write it out to its device
  2377                              <1>         ;xor    al, al ; 26/04/2013       
  2378                              <1> ;1:
  2379                              <1> 		; tstb uquant / is the time quantum 0?
  2380                              <1> 		; bne 1f / no, don't swap it out
  2381                              <1> 
  2382                              <1> sysrele: ; < release >
  2383                              <1> 	; 14/10/2015
  2384                              <1> 	; 01/09/2015
  2385                              <1> 	; 24/07/2015
  2386                              <1> 	; 14/05/2015
  2387                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2388                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2389                              <1> 	;
  2390                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2391                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2392                              <1> 	; turns off the system flag. It then checked to see if there is
  2393                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2394                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2395                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2396                              <1> 	; the user, a rti is made.
  2397                              <1> 	;
  2398                              <1> 	; Calling sequence:
  2399                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2400                              <1> 	; Arguments:
  2401                              <1> 	;	-	
  2402                              <1> 	; ...............................................................
  2403                              <1> 	;	
  2404                              <1> 	; 23/02/2014 (swapret)
  2405                              <1> 	; 22/09/2013
  2406                              <1> sysrel0: ;1:
  2407 0000327B 803D[04670000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2408                              <1> 		; tstb uquant / is the time quantum 0?
  2409 00003282 7705                <1>         ja      short swapret
  2410                              <1> 		; bne 1f / no, don't swap it out
  2411                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2412 00003284 E82B130000          <1> 	call	tswap
  2413                              <1> 		; jsr r0,tswap / yes, swap it out
  2414                              <1> ;
  2415                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2416                              <1> swapret: ;1:
  2417                              <1> 	; 10/09/2015
  2418                              <1> 	; 01/09/2015
  2419                              <1> 	; 14/05/2015
  2420                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2421                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2422                              <1> 	; cli
  2423                              <1> 	; 24/07/2015
  2424                              <1> 	;
  2425                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2426                              <1> 	;; mov	esp, [u.usp]
  2427                              <1> 
  2428                              <1> 	; 22/09/2013
  2429 00003289 E8FD140000          <1> 	call	isintr
  2430                              <1> 	; 20/10/2013
  2431 0000328E 7405                <1> 	jz	short sysrel1
  2432 00003290 E877000000          <1> 	call	intract
  2433                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2434                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2435                              <1> 		               ; / action
  2436                              <1> sysrel1:
  2437 00003295 FA                  <1> 	cli ; 14/10/2015
  2438 00003296 FE0D[BF660000]      <1> 	dec	byte [sysflg]
  2439                              <1> 		; decb sysflg / turn system flag off
  2440 0000329C A1[1B670000]        <1> 	mov     eax, [u.pgdir]
  2441 000032A1 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2442                              <1> 			  ; (others are different than kernel page tables) 
  2443                              <1> 	; 10/09/2015
  2444 000032A4 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2445                              <1> 		; mov (sp)+,sc / restore user registers
  2446                              <1> 		; mov (sp)+,mq
  2447                              <1> 		; mov (sp)+,ac
  2448                              <1> 		; mov (sp)+,r5
  2449                              <1> 		; mov (sp)+,r4
  2450                              <1> 		; mov (sp)+,r3
  2451                              <1> 		; mov (sp)+,r2
  2452                              <1> 	;
  2453 000032A5 A1[C8660000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2454 000032AA 0FA9                <1> 	pop	gs
  2455 000032AC 0FA1                <1> 	pop	fs
  2456 000032AE 07                  <1> 	pop	es
  2457 000032AF 1F                  <1> 	pop	ds
  2458 000032B0 CF                  <1> 	iretd	
  2459                              <1> 		; rti / no, return from interrupt
  2460                              <1> 
  2461                              <1> badsys:
  2462                              <1> 	; 27/02/2022
  2463                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2464                              <1> 	; (Major Modification: 'core' dumping procedure in
  2465                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2466                              <1> 	;	has been changed to print 'Invalid System Call !'
  2467                              <1> 	;	message on the user's console tty.)
  2468                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2469                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2470                              <1> 	; (EAX = Function number)  
  2471                              <1> 	;
  2472 000032B1 FE05[10670000]      <1> 	inc	byte [u.bsys]
  2473                              <1> 	;
  2474 000032B7 8B1D[C0660000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2475 000032BD 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2476 000032BF E826E4FFFF          <1> 	call	dwordtohex
  2477 000032C4 8915[66600000]      <1> 	mov	[bsys_msg_eip], edx
  2478 000032CA A3[6A600000]        <1> 	mov	[bsys_msg_eip+4], eax
  2479 000032CF A1[C8660000]        <1> 	mov	eax, [u.r0]
  2480 000032D4 E811E4FFFF          <1> 	call	dwordtohex
  2481 000032D9 8915[56600000]      <1> 	mov	[bsys_msg_eax], edx
  2482 000032DF A3[5A600000]        <1> 	mov	[bsys_msg_eax+4], eax
  2483                              <1> 	; 27/02/2022
  2484                              <1> 	;xor	eax, eax
  2485                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2486                              <1> 	;mov	ebx, [u.fofp]
  2487                              <1> 	;mov	[ebx], eax
  2488                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2489                              <1> 	;inc	eax
  2490                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2491                              <1> 		; writei
  2492                              <1> 		; INPUTS ->
  2493                              <1> 		;    r1 - inode number
  2494                              <1> 		;    u.count - byte count to be written
  2495                              <1> 		;    u.base - points to user buffer
  2496                              <1> 		;    u.fofp - points to word with current file offset
  2497                              <1> 		; OUTPUTS ->
  2498                              <1> 		;    u.count - cleared
  2499                              <1> 		;    u.nread - accumulates total bytes passed back	
  2500                              <1> 		;
  2501                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2502                              <1> 	;call	writei
  2503                              <1> 	;;mov	eax, 1
  2504                              <1> 	;jmp	sysexit
  2505                              <1> 
  2506                              <1> 	; 27/02/2022
  2507 000032E4 BE[37600000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2508 000032E9 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2509 000032F0 8A83[23640000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2510 000032F6 C605[37630000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2511 000032FD A2[16670000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2512 00003302 E8B7260000          <1> 	call	print_cmsg
  2513                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2514 00003307 E9FCFEFFFF          <1> 	jmp	error
  2515                              <1> 
  2516                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2517                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2518                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2519                              <1> 		; br 1f / error
  2520                              <1> 		; neg r1 / negate the i-number to open the core image file
  2521                              <1> 		       ; / for writing
  2522                              <1> 		; jsr r0,iopen / open the core image file
  2523                              <1> 		; jsr r0,itrunc / free all associated blocks
  2524                              <1> 		; br 2f
  2525                              <1> ;1:
  2526                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2527                              <1> 		; jsr r0,maknod / make an i-node
  2528                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2529                              <1> ;2:
  2530                              <1> 		; mov $core,u.base / move address core to u.base
  2531                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2532                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2533                              <1> 		; clr u.off / clear user offset
  2534                              <1> 		; jsr r0,writei / write out the core image to the user
  2535                              <1> 		; mov $user,u.base / pt. u.base to user
  2536                              <1> 		; mov $64.,u.count / u.count = 64
  2537                              <1> 		; jsr r0,writei / write out all the user parameters
  2538                              <1> 		; neg r1 / make i-number positive
  2539                              <1> 		; jsr r0,iclose / close the core image file
  2540                              <1> 		; br sysexit /
  2541                              <1> ;3:
  2542                              <1> 		; <core\0\0>
  2543                              <1> 
  2544                              <1> intract: ; / interrupt action
  2545                              <1> 	; 14/10/2015
  2546                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2547                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2548                              <1> 	;
  2549                              <1> 	; Retro UNIX 8086 v1 modification !
  2550                              <1> 	; (Process/task switching and quit routine by using
  2551                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2552                              <1> 	;
  2553                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2554                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2555                              <1> 	;		'intract' will jump to 'sysexit'.
  2556                              <1> 	;	    Intract will return to the caller 
  2557                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2558                              <1> 	; 14/10/2015
  2559 0000330C FB                  <1> 	sti
  2560                              <1> 	; 07/12/2013	
  2561 0000330D 66FF05[08670000]    <1> 	inc 	word [u.quit]
  2562 00003314 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2563 00003316 66FF0D[08670000]    <1> 	dec	word [u.quit]
  2564                              <1> 	; 16/04/2015
  2565 0000331D C3                  <1> 	retn
  2566                              <1> intrct0:	
  2567 0000331E 58                  <1> 	pop	eax ; call intract -> retn
  2568                              <1> 	;
  2569 0000331F 31C0                <1> 	xor 	eax, eax
  2570 00003321 FEC0                <1> 	inc	al  ; mov ax, 1
  2571                              <1> ;;;
  2572                              <1> 	; UNIX v1 original 'intract' routine... 
  2573                              <1> 	; / interrupt action
  2574                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2575                              <1> 		; bne 1f / no, 1f
  2576                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2577                              <1> 	; 1: / now in user area
  2578                              <1> 		; mov r1,-(sp) / save r1
  2579                              <1> 		; mov u.ttyp,r1 
  2580                              <1> 			; / pointer to tty buffer in control-to r1
  2581                              <1> 		; cmpb 6(r1),$177
  2582                              <1> 			; / is the interrupt char equal to "del"
  2583                              <1> 		; beq 1f / yes, 1f
  2584                              <1> 		; clrb 6(r1) 
  2585                              <1> 		        ; / no, clear the byte 
  2586                              <1> 			; / (must be a quit character)
  2587                              <1> 		; mov (sp)+,r1 / restore r1
  2588                              <1> 		; clr u.quit / clear quit flag
  2589                              <1> 		; bis $20,2(sp) 
  2590                              <1> 		    	; / set trace for quit (sets t bit of 
  2591                              <1> 			; / ps-trace trap)
  2592                              <1> 		; rti   ;  / return from interrupt
  2593                              <1> 	; 1: / interrupt char = del
  2594                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2595                              <1> 			   ; / in the buffer
  2596                              <1> 		; mov (sp)+,r1 / restore r1
  2597                              <1> 		; cmp u.intr,$core / should control be 
  2598                              <1> 				; / transferred to loc core?
  2599                              <1> 		; blo 1f
  2600                              <1> 		; jmp *u.intr / user to do rti yes, 
  2601                              <1> 				; / transfer to loc core
  2602                              <1> 	; 1:
  2603                              <1> 		; sys 1 / exit
  2604                              <1> 
  2605                              <1> sysexit: ; <terminate process>
  2606                              <1> 	; 01/02/2022
  2607                              <1> 	; 01/09/2015
  2608                              <1> 	; 31/08/2015
  2609                              <1> 	; 14/05/2015
  2610                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2611                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2612                              <1> 	;
  2613                              <1> 	; 'sysexit' terminates a process. First each file that
  2614                              <1> 	; the process has opened is closed by 'flose'. The process
  2615                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2616                              <1> 	; searched to find children of the dying process. If any of
  2617                              <1> 	; children are zombies (died by not waited for), they are
  2618                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2619                              <1> 	; dying process's parent. When the parent is found, it is
  2620                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2621                              <1> 	; one of these, the dying process just dies. If it is waiting
  2622                              <1> 	; for a child process to die, it notified that it doesn't 
  2623                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2624                              <1> 	; (waiting to active). It is awakened and put on runq by
  2625                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2626                              <1> 	; it will never be run again but stays around until a 'wait'
  2627                              <1> 	; is completed by it's parent process. If the parent is not
  2628                              <1> 	; found, process just dies. This means 'swap' is called with
  2629                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2630                              <1> 	; to write out the process and 'rswap' reads the new process
  2631                              <1> 	; over the one that dies..i.e., the dying process is 
  2632                              <1> 	; overwritten and destroyed.	
  2633                              <1>  	;
  2634                              <1> 	; Calling sequence:
  2635                              <1> 	;	sysexit or conditional branch.
  2636                              <1> 	; Arguments:
  2637                              <1> 	;	-	
  2638                              <1> 	; ...............................................................
  2639                              <1> 	;	
  2640                              <1> 	; Retro UNIX 8086 v1 modification: 
  2641                              <1> 	;       System call number (=1) is in EAX register.
  2642                              <1> 	;
  2643                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2644                              <1> 	;       registers depending of function details.
  2645                              <1> 	;
  2646                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2647                              <1> 	;
  2648                              <1> ; / terminate process
  2649                              <1> 	; AX = 1
  2650                              <1> 	;dec 	ax ; 0
  2651                              <1> 	; 01/02/2022
  2652 00003323 48                  <1> 	dec	eax ; 0
  2653 00003324 66A3[06670000]      <1> 	mov	[u.intr], ax ; 0
  2654                              <1> 		; clr u.intr / clear interrupt control word
  2655                              <1> 		; clr r1 / clear r1
  2656                              <1> 	; AX = 0
  2657                              <1> sysexit_1: ; 1:
  2658                              <1> 	; AX = File descriptor
  2659                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2660                              <1> 		; / Search the whole list
  2661 0000332A E8640D0000          <1> 	call	fclose
  2662                              <1> 		; jsr r0,fclose / close all files the process opened
  2663                              <1> 	;; ignore error return
  2664                              <1> 		; br .+2 / ignore error return
  2665                              <1> 	;inc	ax
  2666 0000332F FEC0                <1> 	inc	al
  2667                              <1> 		; inc r1 / increment file descriptor
  2668                              <1> 	;cmp	ax, 10
  2669 00003331 3C0A                <1> 	cmp	al, 10
  2670                              <1> 		; cmp r1,$10. / end of u.fp list?
  2671 00003333 72F5                <1> 	jb	short sysexit_1
  2672                              <1> 		; blt 1b / no, go back
  2673 00003335 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2674                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2675 0000333C 88A3[43640000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2676                              <1> 		; clrb p.stat-1(r1) / free the process
  2677                              <1> 	;shl	bx, 1
  2678 00003342 D0E3                <1> 	shl	bl, 1
  2679                              <1> 		; asl r1 / use r1 for index into the below tables
  2680 00003344 668B8B[E2630000]    <1> 	mov	cx, [ebx+p.pid-2]
  2681                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2682 0000334B 668B93[02640000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2683                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2684                              <1> 	;xor 	bx, bx ; 0
  2685 00003352 30DB                <1> 	xor	bl, bl ; 0
  2686                              <1> 		; clr r2
  2687 00003354 31F6                <1> 	xor	esi, esi ; 0
  2688                              <1> 		; clr r5 / initialize reg
  2689                              <1> sysexit_2: ; 1:
  2690                              <1> 	        ; / find children of this dying process, 
  2691                              <1> 		; / if they are zombies, free them
  2692                              <1> 	;add	bx, 2
  2693 00003356 80C302              <1> 	add	bl, 2
  2694                              <1> 		; add $2,r2 / search parent process table 
  2695                              <1> 		          ; / for dying process's name
  2696 00003359 66398B[02640000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2697                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2698 00003360 7513                <1> 	jne	short sysexit_4
  2699                              <1> 		; bne 3f / no
  2700                              <1> 	;shr	bx, 1
  2701 00003362 D0EB                <1> 	shr	bl, 1
  2702                              <1> 		; asr r2 / yes, it is a parent
  2703 00003364 80BB[43640000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2704                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2705                              <1> 				     ; / dying process a zombie
  2706 0000336B 7506                <1> 	jne	short sysexit_3 
  2707                              <1> 		; bne 2f / no
  2708 0000336D 88A3[43640000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2709                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2710                              <1> sysexit_3: ; 2:
  2711                              <1> 	;shr	bx, 1
  2712 00003373 D0E3                <1> 	shl	bl, 1
  2713                              <1> 		; asl r2
  2714                              <1> sysexit_4: ; 3:
  2715                              <1> 		; / search the process name table 
  2716                              <1> 		; / for the dying process's parent
  2717 00003375 663993[E2630000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2718                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2719 0000337C 7502                <1> 	jne	short sysexit_5
  2720                              <1> 		; bne 3f / no
  2721 0000337E 89DE                <1> 	mov	esi, ebx
  2722                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2723                              <1> 		          ; / process # x2) in r5
  2724                              <1> sysexit_5: ; 3:
  2725                              <1> 	;cmp	bx, nproc + nproc
  2726 00003380 80FB20              <1> 	cmp	bl, nproc + nproc
  2727                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2728 00003383 72D1                <1> 	jb	short sysexit_2
  2729                              <1> 		; blt 1b / no, go back
  2730                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2731 00003385 21F6                <1> 	and	esi, esi ; r5=r1
  2732 00003387 7431                <1> 	jz	short sysexit_6
  2733                              <1> 		; beq 2f / no parent has been found. 
  2734                              <1> 		       ; / The process just dies
  2735 00003389 66D1EE              <1> 	shr	si, 1
  2736                              <1> 		; asr r1 / set up index to p.stat
  2737 0000338C 8A86[43640000]      <1> 	mov	al, [esi+p.stat-1]
  2738                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2739 00003392 20C0                <1> 	and	al, al
  2740 00003394 7424                <1> 	jz	short sysexit_6
  2741                              <1> 		; beq 2f / if its been freed, 2f
  2742 00003396 3C03                <1> 	cmp	al, 3
  2743                              <1> 		; cmp r2,$3 / is parent a zombie?
  2744 00003398 7420                <1> 	je	short sysexit_6
  2745                              <1> 		; beq 2f / yes, 2f
  2746                              <1> 	; BH = 0
  2747 0000339A 8A1D[11670000]      <1> 	mov	bl, [u.uno]
  2748                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2749 000033A0 C683[43640000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2750                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2751                              <1> 	; 05/02/2014
  2752 000033A7 3C01                <1> 	cmp	al, 1 ; SRUN
  2753 000033A9 740F                <1> 	je	short sysexit_6
  2754                              <1> 	;cmp	al, 2
  2755                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2756                              <1> 			  ; / this child to die
  2757                              <1> 	;jne	short sysexit_6	
  2758                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2759                              <1> 	; 05/02/2014
  2760                              <1> 	; p.stat = 2 --> waiting
  2761                              <1> 	; p.stat = 4 --> sleeping
  2762 000033AB C686[43640000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2763                              <1> 	;dec	byte [esi+p.stat-1]
  2764                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2765 000033B2 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2766                              <1> 	; 
  2767                              <1> 	;mov	ebx, runq + 4
  2768                              <1> 		; mov $runq+4,r2 / on the runq
  2769 000033B5 E8D1120000          <1> 	call	putlu
  2770                              <1> 		; jsr r0, putlu
  2771                              <1> sysexit_6: ; 2:
  2772                              <1> 	; 31/08/2015
  2773                              <1> 		; / the process dies
  2774 000033BA C605[11670000]00    <1> 	mov	byte [u.uno], 0
  2775                              <1> 		; clrb u.uno / put zero as the process number, 
  2776                              <1> 	           ; / so "swap" will
  2777 000033C1 E8F8110000          <1> 	call	swap
  2778                              <1> 		; jsr r0,swap / overwrite process with another process
  2779                              <1> hlt_sys:
  2780                              <1> 	;sti ; 18/01/2014
  2781                              <1> hlts0:
  2782 000033C6 F4                  <1> 	hlt
  2783 000033C7 EBFD                <1> 	jmp	short hlts0
  2784                              <1> 		; 0 / and thereby kill it; halt?
  2785                              <1> 
  2786                              <1> 
  2787                              <1> syswait: ; < wait for a processs to die >
  2788                              <1> 	; 12/02/2022
  2789                              <1> 	; 01/02/2022
  2790                              <1> 	; 17/09/2015
  2791                              <1> 	; 02/09/2015
  2792                              <1> 	; 01/09/2015
  2793                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2794                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2795                              <1> 	;
  2796                              <1> 	; 'syswait' waits for a process die. 
  2797                              <1> 	; It works in following way:
  2798                              <1> 	;    1) From the parent process number, the parent's 
  2799                              <1> 	; 	process name is found. The p.ppid table of parent
  2800                              <1> 	;	names is then searched for this process name.
  2801                              <1> 	;	If a match occurs, r2 contains child's process
  2802                              <1> 	;	number. The child status is checked to see if it is
  2803                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2804                              <1> 	;	If it is, the child process is freed and it's name
  2805                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2806                              <1> 	;	If the child is not a zombie, nothing happens and
  2807                              <1> 	;	the search goes on through the p.ppid table until
  2808                              <1> 	;	all processes are checked or a zombie is found.
  2809                              <1> 	;    2) If no zombies are found, a check is made to see if
  2810                              <1> 	;	there are any children at all. If there are none,
  2811                              <1> 	;	an error return is made. If there are, the parent's
  2812                              <1> 	;	status is set to 2 (waiting for child to die),
  2813                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2814                              <1> 	;	is made to wait on the next process.
  2815                              <1> 	;
  2816                              <1> 	; Calling sequence:
  2817                              <1> 	;	?
  2818                              <1> 	; Arguments:
  2819                              <1> 	;	-
  2820                              <1> 	; Inputs: - 
  2821                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2822                              <1> 	; ...............................................................
  2823                              <1> 	;				
  2824                              <1> 	
  2825                              <1> ; / wait for a process to die
  2826                              <1> 
  2827                              <1> syswait_0:
  2828 000033C9 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2829                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2830 000033D0 D0E3                <1> 	shl	bl, 1
  2831                              <1> 	;shl	bx, 1
  2832                              <1> 		; asl r1 / x2 to get index into p.pid table
  2833 000033D2 668B83[E2630000]    <1> 	mov	ax, [ebx+p.pid-2]
  2834                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2835 000033D9 31F6                <1> 	xor	esi, esi
  2836                              <1> 		; clr r2
  2837 000033DB 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2838                              <1> 	;xor 	cl, cl
  2839                              <1> 		; clr r3 / initialize reg 3
  2840                              <1> syswait_1: ; 1:
  2841                              <1> 	; 12/02/2022
  2842 000033DD 46                  <1> 	inc	esi
  2843 000033DE 46                  <1> 	inc	esi
  2844                              <1> 	;add	si, 2
  2845                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2846                              <1> 			  ; / search table of parent processes 
  2847                              <1> 			  ; / for this process name
  2848 000033DF 663B86[02640000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2849                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2850                              <1> 			            ; / process number
  2851 000033E6 7531                <1> 	jne	short syswait_3
  2852                              <1> 		; bne 3f / branch if no match of parent process name
  2853                              <1> 	;inc	cx
  2854 000033E8 FEC1                <1> 	inc	cl
  2855                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2856                              <1> 	; 12/02/2022
  2857 000033EA D1EE                <1> 	shr	esi, 1
  2858                              <1> 	;shr	si, 1
  2859                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2860                              <1> 	; The possible states ('p.stat' values) of a process are:
  2861                              <1> 	;	0 = free or unused
  2862                              <1> 	;	1 = active
  2863                              <1> 	;	2 = waiting for a child process to die
  2864                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2865 000033EC 80BE[43640000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2866                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2867 000033F3 7522                <1> 	jne	short syswait_2
  2868                              <1> 		; bne 2f / no, skip it
  2869 000033F5 88BE[43640000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2870                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2871                              <1> 	; 12/02/2022
  2872 000033FB D1E6                <1> 	shl	esi, 1
  2873                              <1> 	;shl	si, 1
  2874                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2875 000033FD 0FB786[E2630000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2876 00003404 A3[C8660000]        <1> 	mov	[u.r0], eax
  2877                              <1> 		; mov p.pid-2(r2),*u.r0 
  2878                              <1> 			      ; / put childs process name in (u.r0)
  2879                              <1> 	;
  2880                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2881                              <1> 	;
  2882                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2883                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2884                              <1> 	; system call loop from the application/program if it calls
  2885                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2886                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2887                              <1> 	;
  2888                              <1> 	; Note: syswait will return with error if there is not a
  2889                              <1> 	;       zombie or running process to wait.	
  2890                              <1> 	;
  2891                              <1> 	;sub	ax, ax
  2892                              <1> 	; 01/02/2022
  2893 00003409 29C0                <1> 	sub	eax, eax
  2894 0000340B 668986[02640000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2895 00003412 E913FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2896                              <1> 	;
  2897                              <1> 	;jmp	sysret
  2898                              <1> 		; br sysret1 / return cause child is dead
  2899                              <1> syswait_2: ; 2:
  2900                              <1> 	; 12/02/2022
  2901 00003417 D1E6                <1> 	shl	esi, 1
  2902                              <1> 	;shl	si, 1
  2903                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2904                              <1> syswait_3: ; 3:
  2905 00003419 6683FE20            <1> 	cmp	si, nproc+nproc
  2906                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2907 0000341D 72BE                <1> 	jb	short syswait_1
  2908                              <1> 		; blt 1b / no, continue search
  2909                              <1> 	;and	cx, cx
  2910 0000341F 20C9                <1> 	and	cl, cl
  2911                              <1> 		; tst r3 / one gets here if there are no children 
  2912                              <1> 		       ; / or children that are still active
  2913                              <1> 	; 30/10/2013
  2914 00003421 7515                <1> 	jnz	short syswait_4
  2915                              <1> 	;jz	error
  2916                              <1> 		; beq error1 / there are no children, error
  2917 00003423 890D[C8660000]      <1> 	mov	[u.r0], ecx ; 0
  2918                              <1> 	; 12/02/2022
  2919 00003429 C705[17670000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2919 00003431 0000                <1>
  2920                              <1> 			; miscellaneous/other errors
  2921 00003433 E9D0FDFFFF          <1> 	jmp	error
  2922                              <1> syswait_4:
  2923 00003438 8A1D[11670000]      <1> 	mov	bl, [u.uno]
  2924                              <1> 		; movb u.uno,r1 / there are children so put 
  2925                              <1> 			      ; / parent process number in r1
  2926 0000343E FE83[43640000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2927                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2928                              <1> 				  ; / other children to die
  2929                              <1> 	; 04/11/2013
  2930 00003444 E875110000          <1> 	call	swap
  2931                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2932 00003449 E97BFFFFFF          <1> 	jmp	syswait_0
  2933                              <1> 		; br syswait / wait on next process
  2934                              <1> 
  2935                              <1> sysfork: ; < create a new process >
  2936                              <1> 	; 26/02/2022
  2937                              <1> 	; 25/02/2022
  2938                              <1> 	; 01/02/2022
  2939                              <1> 	; 18/09/2015
  2940                              <1> 	; 04/09/2015
  2941                              <1> 	; 02/09/2015
  2942                              <1> 	; 01/09/2015
  2943                              <1> 	; 28/08/2015
  2944                              <1> 	; 14/05/2015
  2945                              <1> 	; 10/05/2015
  2946                              <1> 	; 09/05/2015
  2947                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2948                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2949                              <1> 	;
  2950                              <1> 	; 'sysfork' creates a new process. This process is referred
  2951                              <1> 	; to as the child process. This new process core image is
  2952                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2953                              <1> 	; distinction is the return location and the fact that (u.r0)
  2954                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2955                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2956                              <1> 	; 'sysfork' works in the following manner: 	
  2957                              <1> 	;    1) The process status table (p.stat) is searched to find
  2958                              <1> 	;	a process number that is unused. If none are found
  2959                              <1> 	;	an error occurs.
  2960                              <1> 	;    2) when one is found, it becomes the child process number
  2961                              <1> 	;	and it's status (p.stat) is set to active.
  2962                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2963                              <1> 	;	character in that tty buffer is cleared.
  2964                              <1> 	;    4) The child process is put on the lowest priority run 
  2965                              <1> 	;	queue via 'putlu'.
  2966                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2967                              <1> 	;	it is a unique number) and is put in the child's unique
  2968                              <1> 	;	identifier; process id (p.pid).
  2969                              <1> 	;    6) The process name of the parent is then obtained and
  2970                              <1> 	;	placed in the unique identifier of the parent process
  2971                              <1> 	;	name is then put in 'u.r0'.	
  2972                              <1> 	;    7) The child process is then written out on disk by
  2973                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2974                              <1> 	;	and the child is born. (The child process is written 
  2975                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2976                              <1> 	;	number.)
  2977                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2978                              <1> 	;    9) The child process name is put in 'u.r0'.
  2979                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2980                              <1> 	;	create the return address for the parent process.
  2981                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2982                              <1> 	;	the parent has opened. For each file the parent has
  2983                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2984                              <1> 	;	to indicate that the child process also has opened
  2985                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2986                              <1> 	;
  2987                              <1> 	; Calling sequence:
  2988                              <1> 	;	from shell ?
  2989                              <1> 	; Arguments:
  2990                              <1> 	;	-
  2991                              <1> 	; Inputs: -
  2992                              <1> 	; Outputs: *u.r0 - child process name
  2993                              <1> 	; ...............................................................
  2994                              <1> 	;	
  2995                              <1> 	; Retro UNIX 8086 v1 modification: 
  2996                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2997                              <1> 	;	= process id of child a parent process returns
  2998                              <1> 	;	= process id of parent when a child process returns
  2999                              <1> 	;
  3000                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3001                              <1> 	;	in following manner: (with an example: c library, fork)
  3002                              <1> 	;	
  3003                              <1> 	;	1:
  3004                              <1> 	;		sys	fork
  3005                              <1> 	;			br 1f  / child process returns here
  3006                              <1> 	;		bes	2f     / parent process returns here
  3007                              <1> 	;		/ pid of new process in r0
  3008                              <1> 	;		rts	pc
  3009                              <1> 	;	2: / parent process condionally branches here
  3010                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3011                              <1> 	;		rts	pc
  3012                              <1> 	;
  3013                              <1> 	;	1: / child process brances here
  3014                              <1> 	;		clr	r0   / pid = 0 in child process
  3015                              <1> 	;		rts	pc
  3016                              <1> 	;
  3017                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3018                              <1> 	;		// pid = fork();
  3019                              <1> 	;		//
  3020                              <1> 	;		// pid == 0 in child process; 
  3021                              <1> 	;		// pid == -1 means error return
  3022                              <1> 	;		// in child, 
  3023                              <1> 	;		//	parents id is in par_uid if needed
  3024                              <1> 	;		
  3025                              <1> 	;		_fork:
  3026                              <1> 	;			mov	$.fork,eax
  3027                              <1> 	;			int	$0x30
  3028                              <1> 	;			jmp	1f
  3029                              <1> 	;			jnc	2f
  3030                              <1> 	;			jmp	cerror
  3031                              <1> 	;		1:
  3032                              <1> 	;			mov	eax,_par_uid
  3033                              <1> 	;			xor	eax,eax
  3034                              <1> 	;		2:
  3035                              <1> 	;			ret
  3036                              <1> 	;
  3037                              <1> 	;	In Retro UNIX 8086 v1,
  3038                              <1> 	;	'sysfork' returns in following manner:
  3039                              <1> 	;	
  3040                              <1> 	;		mov	ax, sys_fork
  3041                              <1> 	;		mov	bx, offset @f ; routine for child
  3042                              <1> 	;		int	20h
  3043                              <1> 	;		jc	error
  3044                              <1> 	;		
  3045                              <1> 	;	; Routine for parent process here (just after 'jc')
  3046                              <1> 	;		mov	word ptr [pid_of_child], ax
  3047                              <1> 	;		jmp	next_routine_for_parent	
  3048                              <1> 	;
  3049                              <1> 	;	@@: ; routine for child process here				
  3050                              <1> 	;		....	
  3051                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3052                              <1> 	;	       for child process by using BX input.
  3053                              <1> 	;	      (at first, parent process will return then 
  3054                              <1> 	;	      child process will return -after swapped in-
  3055                              <1> 	;	      'syswait' is needed in parent process
  3056                              <1> 	;	      if return from child process will be waited for.)
  3057                              <1> 	;	  				
  3058                              <1> 	
  3059                              <1> ; / create a new process
  3060                              <1> 	; EBX = return address for child process 
  3061                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3062 0000344E 31F6                <1> 	xor 	esi, esi
  3063                              <1> 		; clr r1
  3064                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3065 00003450 46                  <1> 	inc	esi
  3066                              <1> 		; inc r1
  3067 00003451 80BE[43640000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3068                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3069 00003458 760B                <1> 	jna	short sysfork_2	
  3070                              <1> 		; beq 1f / it's unused so branch
  3071 0000345A 6683FE10            <1> 	cmp	si, nproc
  3072                              <1> 		; cmp r1,$nproc / all processes checked
  3073 0000345E 72F0                <1> 	jb	short sysfork_1
  3074                              <1> 		; blt 1b / no, branch back
  3075                              <1> 	;
  3076                              <1> 	; Retro UNIX 8086 v1. modification:
  3077                              <1> 	;	Parent process returns from 'sysfork' to address 
  3078                              <1> 	;	which is just after 'sysfork' system call in parent
  3079                              <1> 	;	process. Child process returns to address which is put
  3080                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3081                              <1> 	;
  3082                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3083                              <1> 		               ; / to old process return
  3084                              <1> 		; br error1 / no room for a new process
  3085                              <1> sysfork_err:
  3086 00003460 E9A3FDFFFF          <1> 	jmp	error
  3087                              <1> sysfork_2: ; 1:
  3088 00003465 E897F0FFFF          <1> 	call	allocate_page
  3089                              <1> 	;jc	error
  3090                              <1> 	; 01/02/2022
  3091 0000346A 72F4                <1> 	jc	short sysfork_err
  3092 0000346C 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3093                              <1> 	; Retro UNIX 386 v1 modification!
  3094 0000346D E888F2FFFF          <1> 	call	duplicate_page_dir
  3095                              <1> 		; EAX = New page directory 
  3096 00003472 7308                <1> 	jnc	short sysfork_3
  3097 00003474 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3098 00003475 E84FF2FFFF          <1> 	call 	deallocate_page
  3099                              <1> 	;jmp	error
  3100                              <1> 	; 01/02/2022
  3101 0000347A EBE4                <1> 	jmp	short sysfork_err
  3102                              <1> sysfork_3:
  3103                              <1> 	; Retro UNIX 386 v1 modification !
  3104 0000347C 56                  <1> 	push	esi
  3105 0000347D E8B3110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3106                              <1> 		      ; and interrupt return components (for IRET)
  3107 00003482 8705[1B670000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3108 00003488 A3[1F670000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3109 0000348D 5E                  <1> 	pop	esi
  3110 0000348E 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3111                              <1> 		; [u.usp] = esp
  3112 0000348F 89F7                <1> 	mov	edi, esi
  3113                              <1> 	;shl	di, 2
  3114                              <1> 	; 12/02/2022
  3115 00003491 C1E702              <1> 	shl	edi, 2
  3116 00003494 8987[50640000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3117 0000349A A3[12670000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3118                              <1> 	; 28/08/2015
  3119 0000349F 0FB605[11670000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3120                              <1> 		; movb u.uno,-(sp) / save parent process number
  3121 000034A6 89C7                <1> 	mov	edi, eax
  3122 000034A8 50                  <1>         push	eax ; ** 
  3123 000034A9 8A87[23640000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3124                              <1> 	; 18/09/2015
  3125 000034AF 8886[23640000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3126                              <1> 	; 26/02/2022 (p.waitc is not used)
  3127                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3128                              <1> 	; 25/02/2022 (BugFix)
  3129                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3130                              <1> 	;			   ; ah - reset child's wait channel	
  3131 000034B5 89F0                <1> 	mov	eax, esi
  3132 000034B7 A2[11670000]        <1> 	mov	[u.uno], al ; child process number
  3133                              <1> 		;movb r1,u.uno / set child process number to r1
  3134 000034BC FE86[43640000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3135                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3136                              <1> 				  ; / process to active status
  3137                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3138                              <1> 			      ; / control tty buffer in r2
  3139                              <1>                 ; beq 2f / branch, if no such tty assigned
  3140                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3141                              <1> 	; 2:
  3142 000034C2 53                  <1> 	push	ebx  ; * return address for the child process
  3143                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3144                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3145                              <1> 		; mov $runq+4,r2
  3146 000034C3 E8C3110000          <1> 	call	putlu 
  3147                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3148                              <1> 			   ; / run queue
  3149                              <1> 	; 12/02/2022
  3150 000034C8 D1E6                <1> 	shl	esi, 1
  3151                              <1> 	;shl	si, 1
  3152                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3153                              <1> 		       ; / into p.pid table
  3154 000034CA 66FF05[B6660000]    <1> 	inc	word [mpid]
  3155                              <1> 		; inc mpid / increment m.pid; get a new process name
  3156 000034D1 66A1[B6660000]      <1> 	mov	ax, [mpid]
  3157 000034D7 668986[E2630000]    <1> 	mov	[esi+p.pid-2], ax
  3158                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3159                              <1> 				    ; / in child process' name slot
  3160 000034DE 5A                  <1> 	pop	edx  ; * return address for the child process
  3161                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3162 000034DF 5B                  <1>   	pop	ebx  ; **
  3163                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3164                              <1> 		; movb (sp),r2 / put parent process number in r2
  3165                              <1> 	; 01/02/2022
  3166 000034E0 D0E3                <1> 	shl	bl, 1
  3167                              <1> 	;shl 	bx, 1
  3168                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3169                              <1> 	; ebx <= 32
  3170                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3171 000034E2 668B83[E2630000]    <1> 	mov	ax, [ebx+p.pid-2]
  3172                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3173                              <1> 				   ; / process
  3174 000034E9 668986[02640000]    <1> 	mov	[esi+p.ppid-2], ax
  3175                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3176                              <1> 			  ; / in parent process slot for child
  3177 000034F0 A3[C8660000]        <1> 	mov	[u.r0], eax	
  3178                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3179                              <1> 			     ; / at location where r0 was saved
  3180 000034F5 8B2D[C0660000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3181 000034FB 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3182                              <1> 			   ; * return address for the child process
  3183                              <1> 		; mov $sysret1,-(sp) /
  3184                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3185                              <1> 			      ; / user is swapped out
  3186                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3187                              <1> 	; 04/09/2015 - 01/09/2015
  3188                              <1> 	; [u.usp] = esp
  3189 000034FE 68[28320000]        <1> 	push	sysret ; ***
  3190 00003503 8925[C4660000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3191                              <1> 			     ; (for child process)	
  3192 00003509 31C0                <1> 	xor 	eax, eax
  3193 0000350B 66A3[F8660000]      <1> 	mov 	[u.ttyp], ax ; 0
  3194                              <1> 	;
  3195 00003511 E81F110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3196                              <1> 		;jsr r0,wswap / put child process out on drum
  3197                              <1> 		;jsr r0,unpack / unpack user stack
  3198                              <1> 		;mov u.usp,sp / restore user stack pointer
  3199                              <1> 		; tst (sp)+ / bump stack pointer
  3200                              <1> 	; Retro UNIX 386 v1 modification !
  3201 00003516 58                  <1> 	pop	eax ; ***
  3202                              <1> 	;shl	bx, 1
  3203                              <1> 	; 01/02/2022
  3204 00003517 D0E3                <1> 	shl	bl, 1 
  3205                              <1> 		; ebx <= 64
  3206 00003519 8B83[50640000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3207 0000351F E83A110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3208                              <1> 		      ; registers and return address (for IRET)
  3209                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3210 00003524 0FB705[B6660000]    <1>         movzx   eax, word [mpid]
  3211 0000352B A3[C8660000]        <1> 	mov	[u.r0], eax
  3212                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3213                              <1> 			       ; / where r0 was saved
  3214                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3215                              <1> 			       ; / process return
  3216                              <1> 	;xor	ebx, ebx
  3217 00003530 31F6                <1> 	xor     esi, esi
  3218                              <1> 		;clr r1
  3219                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3220                              <1> 	      ; / opened by the parent process
  3221                              <1> 	; 01/09/2015
  3222                              <1> 	;xor	bh, bh
  3223                              <1> 	;mov 	bl, [esi+u.fp]
  3224 00003532 8A86[CE660000]      <1> 	mov 	al, [esi+u.fp]
  3225                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3226                              <1>         ;or	bl, bl
  3227 00003538 08C0                <1> 	or	al, al
  3228 0000353A 740C                <1> 	jz	short sysfork_5	
  3229                              <1> 		; beq 2f / file has not been opened by parent, 
  3230                              <1> 		       ; / so branch
  3231 0000353C B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3232 0000353E F6E4                <1> 	mul	ah
  3233                              <1> 	;;movzx	ebx, ax
  3234                              <1> 	;mov	bx, ax
  3235 00003540 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3236                              <1> 	;shl	bx, 3
  3237                              <1> 		; asl r2 / multiply by 8
  3238                              <1>        		; asl r2 / to get index into fsp table
  3239                              <1>        		; asl r2
  3240 00003542 FE83[92640000]      <1>   	inc     byte [ebx+fsp-2]
  3241                              <1> 		; incb fsp-2(r2) / increment number of processes
  3242                              <1> 			     ; / using file, because child will now be
  3243                              <1> 			     ; / using this file
  3244                              <1> sysfork_5: ; 2:
  3245 00003548 46                  <1>         inc     esi
  3246                              <1> 		; inc r1 / get next open file
  3247 00003549 6683FE0A            <1>         cmp     si, 10
  3248                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3249                              <1> 			    ; / can be opened
  3250 0000354D 72E3                <1> 	jb	short sysfork_4	
  3251                              <1> 		; blt 1b / check next entry
  3252 0000354F E9D4FCFFFF          <1> 	jmp	sysret
  3253                              <1> 		; br sysret1
  3254                              <1> 
  3255                              <1> sysread: ; < read from file >
  3256                              <1> 	; 27/02/2022
  3257                              <1> 	; 01/02/2022
  3258                              <1> 	; 13/05/2015
  3259                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3260                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3261                              <1> 	;
  3262                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3263                              <1> 	; characters to be read. If finds the file from the file
  3264                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3265                              <1> 	; is returned from a successful open call (sysopen).
  3266                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3267                              <1> 	; is read into core via 'readi'.
  3268                              <1> 	;
  3269                              <1> 	; Calling sequence:
  3270                              <1> 	;	sysread; buffer; nchars
  3271                              <1> 	; Arguments:
  3272                              <1> 	;	buffer - location of contiguous bytes where 
  3273                              <1> 	;		 input will be placed.
  3274                              <1> 	;	nchars - number of bytes or characters to be read.
  3275                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3276                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3277                              <1> 	; ...............................................................
  3278                              <1> 	;				
  3279                              <1> 	; Retro UNIX 8086 v1 modification: 
  3280                              <1> 	;       'sysread' system call has three arguments; so,
  3281                              <1> 	;	* 1st argument, file descriptor is in BX register
  3282                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3283                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3284                              <1> 	;
  3285                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3286                              <1> 	;	to the user with number of bytes read. 
  3287                              <1> 	;
  3288 00003554 E840000000          <1> 	call	rw1
  3289                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3290                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3291                              <1>        	; 27/02/2022
  3292 00003559 7239                <1> 	jc	short sysread_err
  3293 0000355B F6C480              <1> 	test	ah, 80h
  3294                              <1> 		; tst r1 / negative i-number?
  3295                              <1> 	;jnz	error
  3296                              <1> 		; ble error1 / yes, error 1 to read
  3297                              <1> 			   ; / it should be positive
  3298                              <1> 	; 01/02/2022
  3299                              <1> 	;jnz	short rw_error
  3300                              <1> 	;27/02/2022
  3301 0000355E 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3302                              <1> 	;
  3303 00003560 E88D150000          <1> 	call	readi
  3304                              <1> 		; jsr r0,readi / read data into core
  3305 00003565 EB14                <1> 	jmp	short rw0
  3306                              <1> 		; br 1f
  3307                              <1> 
  3308                              <1> syswrite: ; < write to file >
  3309                              <1> 	; 27/02/2022
  3310                              <1> 	; 01/02/2022
  3311                              <1> 	; 13/05/2015
  3312                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3313                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3314                              <1> 	;
  3315                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3316                              <1> 	; and the number of characters to write. If finds the file
  3317                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3318                              <1> 	; descriptor is returned from a successful open or create call
  3319                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3320                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3321                              <1> 	;
  3322                              <1> 	; Calling sequence:
  3323                              <1> 	;	syswrite; buffer; nchars
  3324                              <1> 	; Arguments:
  3325                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3326                              <1> 	;	nchars - number of characters to be written.
  3327                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3328                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3329                              <1> 	; ...............................................................
  3330                              <1> 	;				
  3331                              <1> 	; Retro UNIX 8086 v1 modification: 
  3332                              <1> 	;       'syswrite' system call has three arguments; so,
  3333                              <1> 	;	* 1st argument, file descriptor is in BX register
  3334                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3335                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3336                              <1> 	;
  3337                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3338                              <1> 	;	to the user with number of bytes written. 
  3339                              <1> 	;
  3340 00003567 E82D000000          <1> 	call	rw1
  3341                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3342                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3343                              <1> 	; 01/02/2022
  3344                              <1> 	;jnc	short syswrite_1
  3345                              <1> ;rw_error:
  3346                              <1> 	;jmp	error
  3347                              <1> 	; 27/02/2022
  3348 0000356C 7226                <1> 	jc	short short syswrite_err
  3349                              <1> syswrite_1:
  3350 0000356E F6C480              <1>         test	ah, 80h
  3351                              <1> 		; tst r1 / positive i-number ?
  3352 00003571 7417                <1>         jz	short rw3 ; 13/05/2015
  3353                              <1> 	;jz	error
  3354                              <1> 		; bge error1 / yes, error 1 
  3355                              <1> 			   ; / negative i-number means write
  3356 00003573 66F7D8              <1> 	neg	ax
  3357                              <1> 		; neg r1 / make it positive
  3358 00003576 E865170000          <1> 	call	writei
  3359                              <1>         	; jsr r0,writei / write data
  3360                              <1> rw0: ; 1:
  3361 0000357B A1[F0660000]        <1>         mov	eax, [u.nread]
  3362 00003580 A3[C8660000]        <1> 	mov	[u.r0], eax
  3363                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3364                              <1> 				  ; / into (u.r0)
  3365 00003585 E99EFCFFFF          <1> 	jmp	sysret
  3366                              <1>         	; br sysret1
  3367                              <1> rw3: 
  3368                              <1> 	; 13/05/2015
  3369 0000358A C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3369 00003592 0000                <1>
  3370                              <1> 	;stc
  3371                              <1> 	;retn
  3372                              <1> 	; 27/02/2022 (BugFix)
  3373                              <1> sysread_err:
  3374                              <1> syswrite_err:
  3375 00003594 E96FFCFFFF          <1> 	jmp	error
  3376                              <1> 
  3377                              <1> rw1:	
  3378                              <1> 	; 14/05/2015
  3379                              <1> 	; 13/05/2015
  3380                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3381                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3382                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3383                              <1> 	;
  3384                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3385                              <1> 				;(in the user's virtual memory space)
  3386                              <1> 	;mov	[u.count], edx 
  3387                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3388                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3389                              <1> 	;;mov	eax, ebx ; file descriptor
  3390                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3391                              <1> 		             ; / (index to u.fp table) in r1
  3392                              <1> 	; 13/05/2015
  3393 00003599 C705[C8660000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3393 000035A1 0000                <1>
  3394                              <1> 	;
  3395                              <1> 	;; call	getf
  3396                              <1>         ; eBX = File descriptor
  3397 000035A3 E82E0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3398                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3399                              <1> 	; AX = I-number of the file ; negative i-number means write
  3400                              <1> 	; 13/05/2015
  3401 000035A8 6683F801            <1> 	cmp 	ax, 1
  3402 000035AC 7217                <1> 	jb	short rw2
  3403                              <1> 	;
  3404 000035AE 890D[E8660000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3405                              <1> 				;(in the user's virtual memory space)
  3406 000035B4 8915[EC660000]      <1> 	mov	[u.count], edx 
  3407                              <1> 	; 14/05/2015
  3408 000035BA C705[17670000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3408 000035C2 0000                <1>
  3409 000035C4 C3                  <1> 	retn
  3410                              <1>         	; rts r0
  3411                              <1> rw2:
  3412                              <1> 	; 13/05/2015
  3413 000035C5 C705[17670000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3413 000035CD 0000                <1>
  3414 000035CF C3                  <1> 	retn
  3415                              <1> 
  3416                              <1> sysopen: ;<open file>
  3417                              <1> 	; 12/02/2022
  3418                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3419                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3420                              <1> 	;
  3421                              <1> 	; 'sysopen' opens a file in following manner:
  3422                              <1> 	;    1) The second argument in a sysopen says whether to
  3423                              <1> 	;	open the file ro read (0) or write (>0).
  3424                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3425                              <1> 	;    3) The file is opened by 'iopen'.
  3426                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3427                              <1> 	;	and the user's open file list - u.fp.
  3428                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3429                              <1> 	;	b) An entry for the file is created in the fsp table.
  3430                              <1> 	;	c) The number of this entry is put on u.fp list.
  3431                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3432                              <1> 	;	   to by u.r0.
  3433                              <1> 	;
  3434                              <1> 	; Calling sequence:
  3435                              <1> 	;	sysopen; name; mode
  3436                              <1> 	; Arguments:
  3437                              <1> 	;	name - file name or path name
  3438                              <1> 	;	mode - 0 to open for reading
  3439                              <1> 	;	       1 to open for writing
  3440                              <1> 	; Inputs: (arguments)
  3441                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3442                              <1> 	;		  is put into r0's location on the stack.	
  3443                              <1> 	; ...............................................................
  3444                              <1> 	;				
  3445                              <1> 	; Retro UNIX 8086 v1 modification: 
  3446                              <1> 	;       'sysopen' system call has two arguments; so,
  3447                              <1> 	;	* 1st argument, name is pointed to by BX register
  3448                              <1> 	;	* 2nd argument, mode is in CX register
  3449                              <1> 	;
  3450                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3451                              <1> 	;	to the user with the file descriptor/number 
  3452                              <1> 	;	(index to u.fp list).
  3453                              <1> 	;
  3454                              <1> 	;call	arg2
  3455                              <1> 	; * name - 'u.namep' points to address of file/path name
  3456                              <1> 	;          in the user's program segment ('u.segmnt')
  3457                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3458                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3459                              <1> 	;          which is on top of stack.
  3460                              <1> 	;
  3461                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3462                              <1> 	;
  3463                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3464                              <1> 
  3465 000035D0 891D[E0660000]      <1> 	mov	[u.namep], ebx
  3466                              <1> 	;push	cx
  3467 000035D6 51                  <1> 	push	ecx ; 12/02/2022
  3468 000035D7 E82D0B0000          <1> 	call	namei
  3469                              <1> 		; jsr r0,namei / i-number of file in r1
  3470                              <1>      	;and	ax, ax
  3471                              <1> 	;jz	error ; File not found
  3472 000035DC 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3473                              <1> 	;jc	error ; 27/05/2013
  3474                              <1> 		; br  error2 / file not found
  3475                              <1>    	;pop	dx ; mode
  3476                              <1> 	;push	dx
  3477                              <1> 	; 12/02/2022
  3478                              <1> 	;pop	edx ; * ; mode
  3479                              <1> 	;push	edx ; *
  3480 000035DE 8B1424              <1> 	mov	edx, [esp] ; *
  3481                              <1> 	; edx = open mode (0 or 1)
  3482                              <1> 	;or	dx, dx
  3483 000035E1 08D2                <1> 	or	dl, dl
  3484                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3485                              <1> 		         ; / 0 means, open for read)
  3486 000035E3 7403                <1> 	jz	short sysopen_0
  3487                              <1> 		; beq 1f / yes, leave i-number positive
  3488                              <1> syscreat_0: 
  3489                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3490 000035E5 66F7D8              <1> 	neg	ax
  3491                              <1>         	; neg r1 / open for writing so make i-number negative
  3492                              <1> sysopen_0: ;1:
  3493 000035E8 E88B1B0000          <1> 	call	iopen
  3494                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3495 000035ED 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3496                              <1> 	;and	dx, dx
  3497 000035EE 20D2                <1> 	and	dl, dl
  3498                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3499 000035F0 7403                <1> 	jz	short sysopen_2
  3500                              <1>         	; beq op1 / is open for read op1
  3501                              <1> sysopen_1: ;op0:
  3502 000035F2 66F7D8              <1> 	neg	ax
  3503                              <1>         	; neg r1 
  3504                              <1> 		     ;/ make i-number positive if open for writing [???]
  3505                              <1> 	;; NOTE: iopen always make i-number positive.
  3506                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3507                              <1> sysopen_2: ;op1:
  3508 000035F5 31F6                <1>         xor     esi, esi
  3509                              <1>         	; clr r2 / clear registers
  3510 000035F7 31DB                <1>         xor     ebx, ebx
  3511                              <1> 		; clr r3
  3512                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3513 000035F9 389E[CE660000]      <1>         cmp     [esi+u.fp], bl ; 0
  3514                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3515 000035FF 7625                <1>         jna	short sysopen_4
  3516                              <1> 		; beq 1f / if byte in list is 0 branch
  3517 00003601 46                  <1>         inc     esi
  3518                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3519 00003602 6683FE0A            <1>         cmp     si, 10
  3520                              <1> 		; cmp r2,$10. / reached end of list?
  3521 00003606 72F1                <1> 	jb	short sysopen_3
  3522                              <1> 		; blt 1b / no, go back
  3523                              <1> toomanyf:
  3524                              <1> 	; 14/05/2015
  3525 00003608 C705[17670000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3525 00003610 0000                <1>
  3526 00003612 E9F1FBFFFF          <1> 	jmp	error
  3527                              <1>         	; br error2 / yes, error (no files open)
  3528                              <1> fnotfound: 
  3529                              <1> 	; 14/05/2015
  3530 00003617 C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3530 0000361F 0000                <1>
  3531 00003621 E9E2FBFFFF          <1> 	jmp	error
  3532                              <1> 
  3533                              <1> sysopen_4: ; 1:
  3534 00003626 6683BB[94640000]00  <1>         cmp     word [ebx+fsp], 0
  3535                              <1> 		; tst fsp(r3) / scan fsp entries
  3536 0000362E 7610                <1>         jna     short sysopen_5
  3537                              <1> 		; beq 1f / if 0 branch
  3538                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3539 00003630 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3540                              <1> 		; add $8.,r3 / add 8 to r3 
  3541                              <1> 			; / to bump it to next entry mfsp table
  3542 00003634 6681FBF401          <1>         cmp     bx, nfiles*10
  3543                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3544 00003639 72EB                <1> 	jb	short sysopen_4
  3545                              <1>        		; blt 1b / no, back
  3546 0000363B E9C8FBFFFF          <1> 	jmp	error
  3547                              <1>         	; br error2 / yes, error
  3548                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3549 00003640 668983[94640000]    <1>         mov     [ebx+fsp], ax
  3550                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3551                              <1> 			; / into next available entry in fsp table,
  3552                              <1> 	; 12/02/2022
  3553                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3554                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3555                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3556                              <1> 	;xor	edi, edi
  3557                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3558                              <1> 	;	; clr fsp+4(r3)
  3559                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3560                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3561 00003647 31C0                <1> 	xor	eax, eax
  3562 00003649 8983[98640000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3563 0000364F 668983[9C640000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3564                              <1> 
  3565 00003656 66A1[AC660000]      <1> 	mov	ax, [cdev]
  3566 0000365C 668983[96640000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3567                              <1> 
  3568 00003663 89D8                <1>   	mov	eax, ebx
  3569 00003665 B30A                <1> 	mov	bl, 10
  3570 00003667 F6F3                <1> 	div	bl 
  3571                              <1> 		; asr r3
  3572                              <1> 		; asr r3 / divide by 8 
  3573                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3574 00003669 FEC0                <1> 	inc	al
  3575                              <1>         	; inc r3 / add 1 to get fsp entry number
  3576 0000366B 8886[CE660000]      <1>         mov     [esi+u.fp], al
  3577                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3578                              <1> 			; / next available slot in u.fp list
  3579 00003671 8935[C8660000]      <1>         mov     [u.r0], esi
  3580                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3581                              <1> 			     ; / into r0 loc on stack
  3582 00003677 E9ACFBFFFF          <1>         jmp	sysret
  3583                              <1> 		; br sysret2
  3584                              <1> 
  3585                              <1> 	;
  3586                              <1> 	; 'fsp' table (10 bytes/entry)
  3587                              <1> 	; bit 15				   bit 0
  3588                              <1> 	; ---|-------------------------------------------
  3589                              <1> 	; r/w|		i-number of open file
  3590                              <1> 	; ---|-------------------------------------------
  3591                              <1> 	;		   device number
  3592                              <1> 	; -----------------------------------------------
  3593                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3594                              <1> 	; -----------------------------------------------
  3595                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3596                              <1> 	; ----------------------|------------------------
  3597                              <1> 	;  flag that says file 	| number of processes
  3598                              <1> 	;   has been deleted	| that have file open 
  3599                              <1> 	; ----------------------|------------------------
  3600                              <1> 	;
  3601                              <1> 
  3602                              <1> syscreat: ; < create file >
  3603                              <1> 	; 12/02/2022
  3604                              <1> 	; 01/02/2022
  3605                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3606                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3607                              <1> 	;
  3608                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3609                              <1> 	; u.namep points to name of the file and mode is put
  3610                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3611                              <1> 	; If the file aready exists, it's mode and owner remain 
  3612                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3613                              <1> 	; did not exist, an i-node is created with the new mode via
  3614                              <1> 	; 'maknod' whether or not the file already existed, it is
  3615                              <1> 	; open for writing. The fsp table is then searched for a free
  3616                              <1> 	; entry. When a free entry is found, proper data is placed
  3617                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3618                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3619                              <1> 	; is put in the user's r0. 			
  3620                              <1> 	;
  3621                              <1> 	; Calling sequence:
  3622                              <1> 	;	syscreate; name; mode
  3623                              <1> 	; Arguments:
  3624                              <1> 	;	name - name of the file to be created
  3625                              <1> 	;	mode - mode of the file to be created
  3626                              <1> 	; Inputs: (arguments)
  3627                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3628                              <1> 	;		   (the file descriptor of new file)
  3629                              <1> 	; ...............................................................
  3630                              <1> 	;				
  3631                              <1> 	; Retro UNIX 8086 v1 modification: 
  3632                              <1> 	;       'syscreate' system call has two arguments; so,
  3633                              <1> 	;	* 1st argument, name is pointed to by BX register
  3634                              <1> 	;	* 2nd argument, mode is in CX register
  3635                              <1> 	;
  3636                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3637                              <1> 	;	to the user with the file descriptor/number 
  3638                              <1> 	;	(index to u.fp list).
  3639                              <1> 	;
  3640                              <1> 	;call	arg2
  3641                              <1> 	; * name - 'u.namep' points to address of file/path name
  3642                              <1> 	;          in the user's program segment ('u.segmnt')
  3643                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3644                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3645                              <1> 	;          which is on top of stack.
  3646                              <1> 	;
  3647                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3648                              <1> 			    ; / on stack
  3649 0000367C 891D[E0660000]      <1> 	mov	[u.namep], ebx ; file name address
  3650                              <1> 	;push	cx ; mode
  3651                              <1> 	; 01/02/2022
  3652 00003682 51                  <1> 	push	ecx ; mode
  3653 00003683 E8810A0000          <1> 	call 	namei        	
  3654                              <1> 		; jsr r0,namei / get the i-number
  3655                              <1>         ;and	ax, ax
  3656                              <1> 	;jz	short syscreat_2	       	
  3657 00003688 721B                <1> 	jc	short syscreat_2
  3658                              <1> 		; br  2f / if file doesn't exist 2f
  3659                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3660                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3661 0000368A 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3662                              <1>         ;jb	syscreat_0 ; yes
  3663                              <1> 	; 02/02/2022
  3664 0000368E 7305                <1> 	jnb	short syscreat_1
  3665 00003690 E950FFFFFF          <1> 	jmp	syscreat_0
  3666                              <1> syscreat_1:
  3667 00003695 66F7D8              <1> 	neg 	ax
  3668                              <1>         	; neg r1 / if file already exists make i-number 
  3669                              <1> 		       ; / negative (open for writing)
  3670 00003698 E8DB1A0000          <1> 	call	iopen
  3671                              <1>         	; jsr r0,iopen /
  3672 0000369D E8A8130000          <1> 	call	itrunc
  3673                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3674                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3675                              <1> 	; 01/02/2022
  3676 000036A2 59                  <1> 	pop	ecx ; mode
  3677                              <1> 	; 12/02/2022
  3678 000036A3 EB0E                <1> 	jmp	short syscreat_3
  3679                              <1>         ;jmp	sysopen_1
  3680                              <1>         	; br op0
  3681                              <1> syscreat_2: ; 2: / file doesn't exist
  3682                              <1> 	; 01/02/2022
  3683 000036A5 58                  <1> 	pop	eax ; mode
  3684                              <1> 	;pop	ax
  3685                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3686 000036A6 30E4                <1> 	xor	ah, ah	
  3687                              <1>         	; bic $!377,r1 / clear upper byte
  3688 000036A8 E86D0D0000          <1> 	call 	maknod
  3689                              <1>         	; jsr r0,maknod / make an i-node for this file
  3690 000036AD 66A1[FA660000]      <1> 	mov	ax, [u.dirbuf]
  3691                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3692                              <1> 			        ; / for this new file in r1
  3693                              <1> syscreat_3:
  3694 000036B3 E93AFFFFFF          <1>         jmp     sysopen_1
  3695                              <1>         	; br op0 / open the file
  3696                              <1> 
  3697                              <1> sysmkdir: ; < make directory >
  3698                              <1> 	; 01/02/2022
  3699                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3700                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3701                              <1> 	;
  3702                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3703                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3704                              <1> 	; The special entries '.' and '..' are not present.
  3705                              <1> 	; Errors are indicated if the directory already exists or		
  3706                              <1> 	; user is not the super user. 
  3707                              <1> 	;
  3708                              <1> 	; Calling sequence:
  3709                              <1> 	;	sysmkdir; name; mode
  3710                              <1> 	; Arguments:
  3711                              <1> 	;	name - points to the name of the directory
  3712                              <1> 	;	mode - mode of the directory
  3713                              <1> 	; Inputs: (arguments)
  3714                              <1> 	; Outputs: -
  3715                              <1> 	;    (sets 'directory' flag to 1; 
  3716                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3717                              <1> 	; ...............................................................
  3718                              <1> 	;				
  3719                              <1> 	; Retro UNIX 8086 v1 modification: 
  3720                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3721                              <1> 	;	* 1st argument, name is pointed to by BX register
  3722                              <1> 	;	* 2nd argument, mode is in CX register
  3723                              <1> 		
  3724                              <1> ; / make a directory
  3725                              <1> 	
  3726                              <1> 	;call	arg2
  3727                              <1> 	; * name - 'u.namep' points to address of file/path name
  3728                              <1> 	;          in the user's program segment ('u.segmnt')
  3729                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3730                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3731                              <1> 	;          which is on top of stack.
  3732                              <1> 
  3733                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3734                              <1> 			    ; / on stack
  3735 000036B8 891D[E0660000]      <1> 	mov	[u.namep], ebx
  3736                              <1> 	;push	cx ; mode
  3737                              <1> 	; 01/02/2022
  3738 000036BE 51                  <1> 	push	ecx ; mode
  3739 000036BF E8450A0000          <1> 	call	namei
  3740                              <1>         	; jsr r0,namei / get the i-number
  3741                              <1>         	;     br .+4 / if file not found branch around error
  3742                              <1>         ;xor 	ax, ax
  3743                              <1> 	;jnz	error
  3744 000036C4 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3745                              <1> 	;jnc	error	
  3746                              <1> 		; br  error2 / directory already exists (error)
  3747 000036C6 803D[0E670000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3748                              <1>         	;tstb u.uid / is user the super user
  3749                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3750                              <1> 	;;jna	error
  3751                              <1> 	; 01/02/2022 (BugFix)
  3752 000036CD 7721                <1> 	ja	short dir_access_err
  3753                              <1>         	;bne error2 / no, not allowed
  3754                              <1> 	;pop	ax
  3755                              <1> 	; 01/02/2022
  3756 000036CF 58                  <1> 	pop	eax ; mode
  3757                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3758 000036D0 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3759                              <1>         	;bic $!317,r1 / all but su and ex
  3760                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3761 000036D4 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3762                              <1>         	;bis $40000,r1 / directory flag
  3763 000036D7 E83E0D0000          <1> 	call	maknod
  3764                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3765                              <1> sysclose_sysret: ; 01/02/2022
  3766 000036DC E947FBFFFF          <1> 	jmp	sysret
  3767                              <1>         	;br sysret2 /
  3768                              <1> dir_exists:
  3769                              <1> 	; 14/05/2015
  3770 000036E1 C705[17670000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3770 000036E9 0000                <1>
  3771 000036EB E918FBFFFF          <1> 	jmp	error
  3772                              <1> dir_access_err:
  3773                              <1> 	; 14/05/2015
  3774 000036F0 C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3774 000036F8 0000                <1>
  3775 000036FA E909FBFFFF          <1> 	jmp	error
  3776                              <1> 
  3777                              <1> sysclose: ;<close file>
  3778                              <1> 	; 01/02/2022
  3779                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3780                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3781                              <1> 	;
  3782                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3783                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3784                              <1> 	; is put in r1 and 'fclose' is called.
  3785                              <1> 	;
  3786                              <1> 	; Calling sequence:
  3787                              <1> 	;	sysclose
  3788                              <1> 	; Arguments:
  3789                              <1> 	;	-  
  3790                              <1> 	; Inputs: *u.r0 - file descriptor
  3791                              <1> 	; Outputs: -
  3792                              <1> 	; ...............................................................
  3793                              <1> 	;				
  3794                              <1> 	; Retro UNIX 8086 v1 modification:
  3795                              <1> 	;	 The user/application program puts file descriptor
  3796                              <1> 	;        in BX register as 'sysclose' system call argument.
  3797                              <1> 	; 	 (argument transfer method 1)
  3798                              <1> 
  3799                              <1> 	; / close the file
  3800                              <1> 	
  3801 000036FF 89D8                <1> 	mov 	eax, ebx
  3802 00003701 E88D090000          <1> 	call 	fclose
  3803                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3804                              <1> 		; jsr r0,fclose / close the file
  3805                              <1>                	; br error2 / unknown file descriptor
  3806                              <1> 		; br sysret2
  3807                              <1> 	; 14/05/2015
  3808                              <1> 	;jnc	sysret
  3809                              <1> 	; 01/02/2022
  3810 00003706 73D4                <1> 	jnc	short sysclose_sysret
  3811 00003708 C705[17670000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3811 00003710 0000                <1>
  3812 00003712 E9F1FAFFFF          <1> 	jmp	error
  3813                              <1> 
  3814                              <1> sysemt:
  3815                              <1> 	; 23/02/2022
  3816                              <1> 	; 01/02/2022
  3817                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3818                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3819                              <1> 	;
  3820                              <1> 	; Retro UNIX 8086 v1 modification: 
  3821                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3822                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3823                              <1> 	;
  3824                              <1> 	; Retro UNIX 8086 v1 feature only!
  3825                              <1> 	;	Using purpose: Kernel will start without time-out
  3826                              <1> 	;	(internal clock/timer) functionality.
  3827                              <1> 	;	Then etc/init will enable clock/timer for
  3828                              <1> 	;	multi tasking. (Then it will not be disabled again
  3829                              <1> 	;	except hardware reset/restart.)
  3830                              <1> 
  3831 00003717 803D[0E670000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3832                              <1> 	;;ja	error
  3833                              <1> 	;ja	badsys ; 14/05/2015
  3834                              <1> 	; 01/02/2022
  3835                              <1> 	;jna	short emt_0
  3836                              <1> 	;jmp	badsys
  3837 0000371E 773A                <1> 	ja	short sysilgins ; jmp badsys
  3838                              <1> emt_0:
  3839 00003720 FA                  <1> 	cli
  3840 00003721 21DB                <1> 	and	ebx, ebx
  3841 00003723 7429                <1> 	jz	short emt_2
  3842                              <1> 	; Enable multi tasking -time sharing-
  3843 00003725 B8[D3460000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3844                              <1> 	; 23/02/2022
  3845 0000372A BA[440A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3846                              <1> emt_1:
  3847 0000372F A3[0A070000]        <1> 	mov	[x_timer], eax
  3848                              <1> 	; 23/02/2022 (Temporary)
  3849 00003734 8915[0E070000]      <1> 	mov	[x_rtci], edx
  3850 0000373A B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3851 0000373C E853020000          <1> 	call	wttyc  ; clear video page
  3852 00003741 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3853 00003743 E84C020000          <1> 	call	wttyc  ; clear video page
  3854                              <1> 	;
  3855 00003748 FB                  <1> 	sti
  3856 00003749 E9DAFAFFFF          <1> 	jmp	sysret
  3857                              <1> emt_2:
  3858                              <1> 	; Disable multi tasking -time sharing-
  3859 0000374E B8[16070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3860                              <1> 	; 23/02/2022
  3861 00003753 BA[4B0A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3862                              <1> 	;
  3863 00003758 EBD5                <1> 	jmp	short emt_1
  3864                              <1> 
  3865                              <1> 	; Original UNIX v1 'sysemt' routine
  3866                              <1> ;sysemt:
  3867                              <1>         ;
  3868                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3869                              <1> 			 ; / in loc 30
  3870                              <1>         ;cmp    30,$core / was the argument a lower address 
  3871                              <1> 			; / than core
  3872                              <1>         ;blo    1f / yes, rtssym
  3873                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3874                              <1> 			; / and less than "ecore"
  3875                              <1>         ;blo    2f / yes, sysret2
  3876                              <1> ;1:
  3877                              <1>         ;mov    $rtssym,30
  3878                              <1> ;2:
  3879                              <1>         ;br     sysret2
  3880                              <1> 
  3881                              <1> 	; 01/02/2022
  3882                              <1> sysilgins:
  3883                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3884                              <1> 	; 03/06/2013
  3885                              <1> 	; Retro UNIX 8086 v1 modification: 
  3886                              <1> 	;	not a valid system call ! (not in use)
  3887                              <1> 	;
  3888 0000375A E952FBFFFF          <1> 	jmp	badsys
  3889                              <1> 	;jmp	error
  3890                              <1> 	;;jmp 	sysret
  3891                              <1> 
  3892                              <1> 	; Original UNIX v1 'sysemt' routine
  3893                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3894                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3895                              <1> 			  ;/ put it in loc 8.,
  3896                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3897                              <1> 		       ; / trap address
  3898                              <1>         ;blo    1f / is the address a user core address?  
  3899                              <1> 		; / yes, go to 2f
  3900                              <1>         ;cmp    10,$ecore
  3901                              <1>         ;blo    2f
  3902                              <1> ;1:
  3903                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3904                              <1> 		    ; / instruction trap address for the system
  3905                              <1> ;2:
  3906                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3907                              <1> 
  3908                              <1> sysmdate: ; < change the modification time of a file >
  3909                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3910                              <1> 	;	(ECX input)
  3911                              <1> 	; 01/02/2022
  3912                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3913                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3914                              <1> 	;
  3915                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3916                              <1> 	; file into core. The user is checked if he is the owner 
  3917                              <1> 	; or super user. If he is neither an error occurs.
  3918                              <1> 	; 'setimod' is then called to set the i-node modification
  3919                              <1> 	; byte and the modification time, but the modification time
  3920                              <1> 	; is overwritten by whatever get put on the stack during
  3921                              <1> 	; a 'systime' system call. This calls are restricted to
  3922                              <1> 	; the super user.		
  3923                              <1> 	;
  3924                              <1> 	; Calling sequence:
  3925                              <1> 	;	sysmdate; name
  3926                              <1> 	; Arguments:
  3927                              <1> 	;	name - points to the name of file
  3928                              <1> 	; Inputs: (arguments)
  3929                              <1> 	; Outputs: -
  3930                              <1> 	; ...............................................................
  3931                              <1> 	;				
  3932                              <1> 	; Retro UNIX 8086 v1 modification: 
  3933                              <1> 	;	 The user/application program puts address 
  3934                              <1> 	;	 of the file name in BX register 
  3935                              <1> 	;	 as 'sysmdate' system call argument.
  3936                              <1> 	;
  3937                              <1> ; / change the modification time of a file
  3938                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3939 0000375F 891D[E0660000]      <1>         mov	[u.namep], ebx
  3940                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3941 00003765 890D[50630000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3942 0000376B E899090000          <1> 	call	namei
  3943                              <1> 		; jsr r0,namei / get its i-number
  3944                              <1> 	;;jc	error       
  3945                              <1> 		; br error2 / no, such file
  3946                              <1> 	;jc	fnotfound ; file not found !
  3947                              <1> 	; 01/02/2022
  3948 00003770 7305                <1> 	jnc	short mdate_0
  3949 00003772 E9A0FEFFFF          <1> 	jmp	fnotfound
  3950                              <1> mdate_0:
  3951 00003777 E8A2110000          <1> 	call	iget
  3952                              <1> 		; jsr r0,iget / get i-node into core
  3953 0000377C A0[0E670000]        <1> 	mov	al, [u.uid]
  3954 00003781 3A05[C7630000]      <1> 	cmp	al, [i.uid]
  3955                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3956 00003787 7413                <1> 	je	short mdate_1
  3957                              <1>         	; beq 1f / yes
  3958 00003789 20C0                <1> 	and	al, al
  3959                              <1> 		; tstb u.uid / no, is user the super user
  3960                              <1> 	;jnz	error
  3961                              <1> 		; bne error2 / no, error
  3962 0000378B 740F                <1> 	jz	short mdate_1
  3963 0000378D C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3963 00003795 0000                <1>
  3964                              <1> sysstty_err:	; 01/02/2022
  3965 00003797 E96CFAFFFF          <1> 	jmp	error
  3966                              <1> mdate_1: ;1:
  3967 0000379C E887120000          <1> 	call	setimod
  3968                              <1>         	; jsr r0,setimod / fill in modification data,
  3969                              <1> 		               ; / time etc.
  3970 000037A1 BE[50630000]        <1> 	mov	esi, p_time
  3971 000037A6 BF[DE630000]        <1> 	mov	edi, i.mtim
  3972 000037AB A5                  <1> 	movsd
  3973                              <1> 		; mov 4(sp),i.mtim / move present time to
  3974                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3975 000037AC E977FAFFFF          <1>         jmp	sysret
  3976                              <1> 		; br sysret2
  3977                              <1> 
  3978                              <1> 	; 01/02/2022
  3979                              <1> sysstty_err_s:
  3980 000037B1 880D[C8660000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3981 000037B7 EBDE                <1> 	jmp	short sysstty_err
  3982                              <1> 
  3983                              <1> sysstty: ; < set tty status and mode >
  3984                              <1> 	; 23/02/2022
  3985                              <1> 	; 22/02/2022
  3986                              <1> 	; 02/02/2022
  3987                              <1> 	; 01/02/2022 (clear screen)
  3988                              <1> 	; 17/11/2015
  3989                              <1> 	; 12/11/2015
  3990                              <1> 	; 29/10/2015
  3991                              <1> 	; 17/10/2015
  3992                              <1> 	; 13/10/2015
  3993                              <1> 	; 29/06/2015
  3994                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3995                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3996                              <1> 	;
  3997                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3998                              <1> 	; whose file descriptor is in (u.r0).
  3999                              <1> 	;
  4000                              <1> 	; Calling sequence:
  4001                              <1> 	;	sysstty; arg
  4002                              <1> 	; Arguments:
  4003                              <1> 	;	arg - address of 3 consequitive words that contain
  4004                              <1> 	;	      the source of status data	
  4005                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4006                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4007                              <1> 	; ...............................................................
  4008                              <1> 	;	
  4009                              <1> 	; Retro UNIX 8086 v1 modification: 
  4010                              <1> 	;	'sysstty' system call will set the tty
  4011                              <1> 	;	(clear keyboard buffer and set cursor position)
  4012                              <1> 	;	 in following manner:
  4013                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4014                              <1> 	;
  4015                              <1> 	; Inputs:
  4016                              <1> 	;	BX = 0 --> means
  4017                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4018                              <1> 	;	      set cursor position for console tty, only 
  4019                              <1> 	;	      CH will be ignored (char. will not be written)	
  4020                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4021                              <1> 	;	      set console tty for (current) process
  4022                              <1> 	;	      CL = tty number (0 to 9)
  4023                              <1> 	;	      (If CH = 0, character will not be written)
  4024                              <1> 	;          If CH > 0 (CL < FFh)	
  4025                              <1> 	;             CL = tty number (0 to 9)
  4026                              <1> 	;	      CH = character will be written
  4027                              <1> 	;	        at requested cursor position (in DX)	
  4028                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4029                              <1>   	;		(only tty number 0 to 7) 
  4030                              <1> 	;          DL = communication parameters (for serial ports) 
  4031                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4032                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4033                              <1> 	;			or set cursor position	
  4034                              <1> 	;	   DH = 0FFh -> DL is not valid
  4035                              <1> 	;		do not set serial port parameters 
  4036                              <1> 	;		or do not set cursor position
  4037                              <1> 	;
  4038                              <1> 	;	BX > 0 --> points to name of tty
  4039                              <1> 	;    	   CH > 0 -->
  4040                              <1> 	;		CH = character will be written in current 
  4041                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4042                              <1> 	;	     	or character will be sent to serial port
  4043                              <1> 	;	     	(for tty number 8 or 9)
  4044                              <1> 	;		CL = color of the character if tty number < 8.
  4045                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4046                              <1> 	;		set mode (tty 8 to 9) or 
  4047                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4048                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4049                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4050                              <1> 	;		(DL is not valid)
  4051                              <1> 	;	   DL = communication parameters 
  4052                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4053                              <1> 	;
  4054                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4055                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4056                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4057                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4058                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4059                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4060                              <1> 	;
  4061                              <1> 	; Outputs:
  4062                              <1> 	;	cf = 0 -> OK
  4063                              <1> 	;	     AL = tty number (0 to 9)
  4064                              <1> 	;	     AH = line status if tty number is 8 or 9
  4065                              <1> 	;	     AH = process number (of the caller) 	
  4066                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4067                              <1> 	;	     AH = FFh if the tty is locked 
  4068                              <1> 	;		  (owned by another process)
  4069                              <1> 	;	        = process number (of the caller) 
  4070                              <1> 	;		  (if < FFh and tty number < 8)
  4071                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4072                              <1> 	;	     AH = line status if tty number is 8 or 9
  4073                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4074                              <1> 	;	
  4075                              <1> 
  4076                              <1> 	; 27/06/2015 (32 bit modifications)
  4077                              <1> 	; 14/01/2014
  4078 000037B9 31C0                <1> 	xor 	eax, eax
  4079 000037BB 6648                <1> 	dec	ax ; 17/10/2015
  4080 000037BD A3[C8660000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4081                              <1> 	;;;
  4082                              <1> 	; 01/02/2022
  4083 000037C2 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4084 000037C4 39C2                <1> 	cmp	edx, eax
  4085                              <1> 	;cmp	dx, ax ; 0FFFFh
  4086 000037C6 7521                <1> 	jne	short sysstty_18
  4087                              <1> 	; clear video page
  4088                              <1> 	; (CH must be 0)
  4089 000037C8 08ED                <1> 	or	ch, ch
  4090 000037CA 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4091 000037CC 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4092 000037CF 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4093 000037D1 20C9                <1> 	and	cl, cl
  4094 000037D3 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4095 000037D5 0FB635[11670000]    <1> 	movzx	esi, byte [u.uno]
  4096 000037DC 8A8E[23640000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4097 000037E2 80F907              <1> 	cmp	cl, 7
  4098 000037E5 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4099                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4100 000037E7 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4101                              <1> sysstty_18:
  4102 000037E9 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4103                              <1> 	; cl = video page (tty) number		
  4104                              <1> 	;;;
  4105 000037EB 21DB                <1> 	and	ebx, ebx
  4106                              <1> 	;jnz	sysstty_6
  4107                              <1> 	; 01/02/2022
  4108 000037ED 7405                <1> 	jz	short sysstty_19
  4109 000037EF E9C2000000          <1> 	jmp	sysstty_6
  4110                              <1> sysstty_19:
  4111                              <1> 	; set console tty
  4112                              <1> 	; 29/10/2015
  4113                              <1> 	; 17/01/2014 
  4114 000037F4 80F909              <1> 	cmp	cl, 9
  4115 000037F7 7613                <1> 	jna	short sysstty_0
  4116                              <1> 	; 17/11/2015
  4117 000037F9 80F9FF              <1> 	cmp	cl, 0FFh
  4118 000037FC 7202                <1> 	jb	short sysstty_13
  4119 000037FE 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4120                              <1> sysstty_13:
  4121 00003800 8A1D[11670000]      <1> 	mov	bl, [u.uno] ; process number
  4122 00003806 8A8B[23640000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4123                              <1> sysstty_0:
  4124                              <1> 	; 29/06/2015
  4125                              <1> 	;push	dx
  4126                              <1> 	;push	cx
  4127                              <1> 	; 01/02/2022
  4128 0000380C 52                  <1> 	push	edx
  4129 0000380D 51                  <1> 	push	ecx
  4130 0000380E 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4131 00003810 88C8                <1> 	mov	al, cl
  4132 00003812 A2[C8660000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4133 00003817 E8F6190000          <1> 	call	ottyp
  4134                              <1> 	; 01/02/2022
  4135 0000381C 59                  <1> 	pop	ecx
  4136 0000381D 5A                  <1> 	pop	edx
  4137                              <1> 	;pop	cx
  4138                              <1> 	;pop	dx
  4139                              <1> 	;
  4140 0000381E 7220                <1> 	jc	short sysstty_pd_err
  4141                              <1> 	;
  4142                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4143                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4144                              <1> 	;
  4145 00003820 80F908              <1> 	cmp	cl, 8
  4146 00003823 720C                <1> 	jb	short sysstty_2
  4147                              <1> 	;
  4148 00003825 80FEFF              <1> 	cmp	dh, 0FFh
  4149 00003828 7407                <1> 	je	short sysstty_2
  4150                              <1> 		; set communication parameters for serial ports
  4151                              <1> 
  4152                              <1> ; 01/02/2022
  4153                              <1> ;	; 29/10/2015
  4154                              <1> ;	mov	ah, dl ; communication parameters
  4155                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4156                              <1> ;		;			 THRE int + RDA int 
  4157                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4158                              <1> ;		;			 THRE int + RDA int 
  4159                              <1> ;	sub	al, al ; 0
  4160                              <1> ;	; 12/07/2014
  4161                              <1> ;	cmp	cl, 9
  4162                              <1> ;	jb	short sysstty_1
  4163                              <1> ;	inc	al
  4164                              <1> ;sysstty_1:
  4165                              <1> ;	; 01/02/2022
  4166                              <1> ;	push	ecx
  4167                              <1> ;	;push	cx
  4168                              <1> ;	; 29/06/2015	
  4169                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4170                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4171                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4172                              <1> ;	; 01/02/2022
  4173                              <1> ;	pop	ecx	
  4174                              <1> ;	;pop	cx
  4175                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4176                              <1> 
  4177                              <1> 	; 01/02/2022
  4178 0000382A E832010000          <1> 	call	sysstty_scp
  4179 0000382F 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4180                              <1> 
  4181                              <1> sysstty_2:
  4182                              <1> 	; 17/01/2014
  4183 00003831 20ED                <1> 	and	ch, ch 	; set cursor position 
  4184                              <1> 			; or comm. parameters ONLY
  4185 00003833 7527                <1> 	jnz	short sysstty_3
  4186                              <1> 	; 01/02/2022
  4187 00003835 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4188 00003839 7214                <1> 	jb	short sysstty_20
  4189                              <1> 	; clear screen (video page)
  4190 0000383B E93D010000          <1> 	jmp	sysstty_14
  4191                              <1> 
  4192                              <1> sysstty_pd_err: ; 29/06/2015
  4193                              <1> 	; 'permission denied !' error
  4194 00003840 C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4194 00003848 0000                <1>
  4195 0000384A E9B9F9FFFF          <1> 	jmp	error
  4196                              <1> 
  4197                              <1> sysstty_20:
  4198 0000384F 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4199 00003856 888B[23640000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4200                              <1> sysstty_3:
  4201                              <1> 	; 16/01/2014
  4202 0000385C 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4203                              <1> 	; 17/11/2015
  4204 0000385E B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4205 00003860 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4206                              <1> 	;jna	sysstty_9
  4207                              <1> 	; 01/02/2022
  4208 00003862 7705                <1> 	ja	short sysstty_12
  4209 00003864 E9C7000000          <1> 	jmp	sysstty_9
  4210                              <1> 
  4211                              <1> sysstty_12:
  4212                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4213                              <1> 	; (Set specified serial port as console tty port)
  4214                              <1> 	; CH = character to be written
  4215                              <1> 	; 15/04/2014
  4216                              <1> 	; CH = 0 --> initialization only
  4217                              <1> 	; AL = character
  4218                              <1> 	; 26/06/2014
  4219 00003869 880D[16670000]      <1> 	mov	[u.ttyn], cl
  4220                              <1> 	; 12/07/2014
  4221 0000386F 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4222                              <1> 	; 02/02/2022
  4223 00003871 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4224 00003873 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4225 00003875 FEC8                <1> 	dec	al  ; 1 -> 0	
  4226                              <1> 	;and	al, al
  4227 00003877 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4228                              <1>  	; 04/07/2014
  4229 00003879 E8581F0000          <1> 	call 	sndc
  4230                              <1> 	; 12/07/2014
  4231 0000387E EB0C                <1> 	jmp	short sysstty_5
  4232                              <1> 
  4233                              <1> sysstty_4:
  4234                              <1> 	; 12/07/2014
  4235                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4236 00003880 88E0                <1> 	mov	al, ah ; 29/06/2015
  4237 00003882 2C08                <1> 	sub	al, 8
  4238                              <1> 	; 27/06/2015
  4239 00003884 E832F4FFFF          <1> 	call	sp_status ; get serial port status
  4240                              <1> 	; AL = Line status, AH = Modem status
  4241                              <1> 	; 12/11/2015
  4242 00003889 3C80                <1> 	cmp	al, 80h
  4243 0000388B F5                  <1> 	cmc
  4244                              <1> sysstty_5:
  4245 0000388C 66A3[C9660000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4246                              <1> 		; EAX bits 16-23 = modem status	
  4247 00003892 9C                  <1> 	pushf
  4248 00003893 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4249 00003895 A0[16670000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4250 0000389A E8961A0000          <1> 	call	cttyp
  4251 0000389F 9D                  <1> 	popf
  4252                              <1> 	;jnc	sysret ; time out error 
  4253                              <1> 	; 01/02/2022
  4254 000038A0 7205                <1> 	jc	short sysstty_tmout_err
  4255 000038A2 E981F9FFFF          <1> 	jmp	sysret
  4256                              <1> 
  4257                              <1> sysstty_tmout_err:
  4258 000038A7 C705[17670000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4258 000038AF 0000                <1>
  4259 000038B1 E952F9FFFF          <1> 	jmp	error
  4260                              <1> 
  4261                              <1> sysstty_6:
  4262                              <1> 	;push	dx
  4263                              <1> 	;push	cx
  4264                              <1> 	; 01/02/2022
  4265 000038B6 52                  <1> 	push	edx
  4266 000038B7 51                  <1> 	push	ecx
  4267 000038B8 891D[E0660000]      <1> 	mov	[u.namep], ebx
  4268 000038BE E846080000          <1> 	call	namei
  4269                              <1> 	; 01/02/2022
  4270 000038C3 59                  <1> 	pop	ecx
  4271 000038C4 5A                  <1> 	pop	edx
  4272                              <1> 	;pop	cx
  4273                              <1> 	;pop	dx
  4274 000038C5 725A                <1> 	jc	short sysstty_inv_dn
  4275                              <1> 	;
  4276 000038C7 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4277 000038CB 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4278                              <1> 	;
  4279 000038CD 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4280                              <1> 		       ; /dev/COM1, /dev/COM2
  4281 000038CF 7206                <1> 	jb	short sysstty_7
  4282 000038D1 2C0A                <1> 	sub	al, 10
  4283                              <1> 	; al = 0 to 9
  4284 000038D3 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4285 000038D5 EB11                <1> 	jmp	short sysstty_8
  4286                              <1> 
  4287                              <1> sysstty_7:
  4288 000038D7 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4289 000038D9 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4290 000038DB 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4291 000038E2 8A83[23640000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4292                              <1> sysstty_8:
  4293                              <1> 	; 22/02/2022
  4294                              <1> 	; (ebx < 256)
  4295 000038E8 A2[C8660000]        <1> 	mov	[u.r0], al
  4296                              <1> 	; 01/02/2022
  4297                              <1> 	;push	dx
  4298                              <1> 	;push	ax
  4299                              <1> 	;push	cx
  4300 000038ED 52                  <1> 	push	edx
  4301 000038EE 50                  <1> 	push	eax
  4302 000038EF 51                  <1> 	push	ecx
  4303 000038F0 E81D190000          <1> 	call	ottyp
  4304 000038F5 59                  <1> 	pop	ecx
  4305 000038F6 58                  <1> 	pop	eax
  4306 000038F7 5A                  <1> 	pop	edx
  4307                              <1> 	;pop	cx
  4308                              <1> 	;pop	ax
  4309                              <1> 	;pop	dx
  4310                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4311                              <1> 	; 01/02/2022
  4312 000038F8 7305                <1> 	jnc	short sysstty_21
  4313 000038FA E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4314                              <1> sysstty_21:
  4315                              <1> 	; 29/10/2015
  4316 000038FF 86E9                <1> 	xchg 	ch, cl
  4317                              <1> 		; cl = character, ch = color code
  4318 00003901 86C1                <1> 	xchg	al, cl
  4319                              <1> 		; al = character, cl = tty number
  4320 00003903 80F907              <1> 	cmp	cl, 7
  4321                              <1> 	;ja	sysstty_12
  4322                              <1> 	; 01/02/2022
  4323 00003906 7628                <1> 	jna	short sysstty_16
  4324                              <1> ;;
  4325 00003908 80FEFF              <1> 	cmp	dh, 0FFh
  4326 0000390B 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4327                              <1> 
  4328                              <1> ; 01/02/2022
  4329                              <1> ;	; 29/10/2015
  4330                              <1> ;	mov	ah, dl ; communication parameters
  4331                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4332                              <1> ;		;			 THRE int + RDA int 
  4333                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4334                              <1> ;		;			 THRE int + RDA int 
  4335                              <1> ;	sub	al, al ; 0
  4336                              <1> ;	; 12/07/2014
  4337                              <1> ;	cmp	cl, 9
  4338                              <1> ;	jb	short sysstty_1
  4339                              <1> ;	inc	al
  4340                              <1> ;sysstty_1:
  4341                              <1> ;	; 01/02/2022
  4342                              <1> ;	push	ecx
  4343                              <1> ;	;push	cx
  4344                              <1> ;	; 29/06/2015	
  4345                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4346                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4347                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4348                              <1> ;	; 01/02/2022
  4349                              <1> ;	pop	ecx	
  4350                              <1> ;	;pop	cx
  4351                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4352                              <1> 
  4353                              <1> 	; 02/02/2022
  4354 0000390D 88C5                <1> 	mov	ch, al ; save char
  4355                              <1> 	; 01/02/2022
  4356 0000390F E84D000000          <1> 	call	sysstty_scp
  4357 00003914 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4358                              <1> 	; 02/02/2022
  4359 00003916 88E8                <1> 	mov	al, ch ; restore char
  4360                              <1> sysstty_22:
  4361                              <1> 	; 01/02/2022
  4362 00003918 08ED                <1> 	or	ch, ch
  4363 0000391A 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4364                              <1> 	; send char to (serial port) terminal
  4365                              <1> 	; al = character
  4366                              <1> 	; cl = tty number (8 or 9)
  4367 0000391C E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4368                              <1> 
  4369                              <1> sysstty_inv_dn: 
  4370                              <1> 	; 27/06/2015
  4371                              <1> 	; Invalid device name (not a tty) ! error
  4372                              <1> 	; (Device is not a tty or device name not found)
  4373 00003921 C705[17670000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4373 00003929 0000                <1>
  4374 0000392B E9D8F8FFFF          <1> 	jmp	error 
  4375                              <1> 
  4376                              <1> sysstty_16:
  4377                              <1> 	; 22/02/2022
  4378                              <1> 	; 16/01/2014
  4379                              <1> 	;xor	bh, bh
  4380                              <1> sysstty_9: 	; tty 0 to tty 7
  4381                              <1> 	; al = character
  4382                              <1> 	; ch = color/attribute ; 01/02/2022
  4383                              <1> 	;
  4384                              <1>  	; 22/02/2022 (BugFix)
  4385                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4386 00003930 29DB                <1> 	sub	ebx, ebx ; *
  4387 00003932 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4388                              <1> 	;
  4389 00003934 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4390 00003937 7409                <1> 	je	short sysstty_10
  4391                              <1> 	; 02/02/2022
  4392 00003939 51                  <1> 	push	ecx
  4393 0000393A 50                  <1> 	push	eax
  4394                              <1> 	;push	cx
  4395                              <1> 	;push	ax	
  4396                              <1> 	; 22/02/2022	
  4397                              <1> 	;;movzx	ebx, cl ; *
  4398                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4399 0000393B E886DBFFFF          <1> 	call	set_cpos
  4400                              <1> 	;pop	ax
  4401                              <1> 	;pop	cx
  4402                              <1> 	; 02/02/2022
  4403 00003940 58                  <1> 	pop	eax
  4404 00003941 59                  <1> 	pop	ecx
  4405                              <1> sysstty_10: 
  4406                              <1> 	; 29/10/2015
  4407 00003942 08C0                <1> 	or	al, al ; character
  4408 00003944 740D                <1> 	jz      short sysstty_11 ; al = 0
  4409                              <1> 	; 17/11/2015
  4410 00003946 3CFF                <1> 	cmp	al, 0FFh
  4411 00003948 7309                <1> 	jnb	short sysstty_11
  4412                              <1> 		; ch > 0 and ch < FFh
  4413                              <1> 	; write a character at current cursor position
  4414 0000394A 88EC                <1> 	mov	ah, ch ; color/attribute
  4415                              <1> 	; 12/07/2014
  4416                              <1> 	;push	cx
  4417                              <1> 	; 02/02/2022
  4418 0000394C 51                  <1> 	push	ecx
  4419 0000394D E85CDCFFFF          <1> 	call	write_c_current
  4420                              <1> 	;pop	cx
  4421                              <1> 	; 02/02/2022
  4422 00003952 59                  <1> 	pop	ecx
  4423                              <1> sysstty_11:
  4424                              <1> 	; 14/01/2014
  4425 00003953 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4426                              <1> 	; 18/01/2014
  4427                              <1> 	;movzx	eax, cl ; 27/06/2015
  4428 00003955 88C8                <1> 	mov	al, cl
  4429 00003957 E8D9190000          <1> 	call	cttyp
  4430 0000395C E9C7F8FFFF          <1> 	jmp	sysret
  4431                              <1> 
  4432                              <1> sysstty_scp:
  4433                              <1> 	; 02/02/2022
  4434                              <1> 	; set communication parameters (for COM1 or COM2)
  4435                              <1> 	; 01/02/2022
  4436                              <1> 	;
  4437                              <1> 	; 29/10/2015
  4438 00003961 88D4                <1> 	mov	ah, dl ; communication parameters
  4439                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4440                              <1> 		;			 THRE int + RDA int 
  4441                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4442                              <1> 		;			 THRE int + RDA int 
  4443 00003963 28C0                <1> 	sub	al, al ; 0
  4444                              <1> 	; 12/07/2014
  4445 00003965 80F909              <1> 	cmp	cl, 9
  4446 00003968 7202                <1> 	jb	short sysstty_1
  4447 0000396A FEC0                <1> 	inc	al
  4448                              <1> sysstty_1:
  4449                              <1> 	; 02/02/2022
  4450 0000396C 52                  <1> 	push	edx
  4451                              <1> 	; 01/02/2022
  4452 0000396D 51                  <1> 	push	ecx
  4453                              <1> 	;push	cx
  4454                              <1> 	; 29/06/2015	
  4455 0000396E E850F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4456 00003973 66890D[C9660000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4457                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4458                              <1> 	; 01/02/2022
  4459 0000397A 59                  <1> 	pop	ecx	
  4460                              <1> 	;pop	cx
  4461 0000397B 5A                  <1> 	pop	edx ; 02/02/2022
  4462                              <1> 	; 01/02/2022
  4463                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4464 0000397C C3                  <1> 	retn
  4465                              <1> 
  4466                              <1> sysstty_14:
  4467                              <1> 	; 23/02/2022
  4468                              <1> 	; 02/02/2022
  4469                              <1> 	; ch = 0
  4470                              <1> 	; cl = video page
  4471                              <1> 	;
  4472                              <1> 	; dx = 0FFFFh
  4473                              <1> 	; clear screen (video page)
  4474                              <1> 	;
  4475                              <1> 
  4476                              <1> 	; 02/02/2022
  4477                              <1> 	; clear screen
  4478                              <1> 	;
  4479                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4480                              <1> 
  4481                              <1> 	; 23/02/2022
  4482 0000397D 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4483                              <1> 
  4484                              <1> 	; clear video page
  4485 0000397F E810000000          <1> 	call	wttyc ; 23/02/2022
  4486                              <1> 
  4487                              <1> 	; 23/02/2022
  4488 00003984 88D8                <1> 	mov	al, bl
  4489 00003986 8A25[11670000]      <1> 	mov	ah, [u.uno]
  4490 0000398C 66A3[C8660000]      <1> 	mov	[u.r0], ax
  4491 00003992 EBBF                <1> 	jmp	short sysstty_11
  4492                              <1> 
  4493                              <1> vp_clr:	; 27/02/2022
  4494                              <1> wttyc:
  4495                              <1> 	; 23/02/2022
  4496                              <1> 	; (clear video page)
  4497                              <1> 	; INPUT:
  4498                              <1> 	;  bl = video page (0 to 7)
  4499                              <1> 	;
  4500                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4501                              <1> 
  4502                              <1> 	;xor	dx, dx ; column 0, row 0
  4503                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4504                              <1> 	;
  4505                              <1> ;	movzx	ebx, cl
  4506                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4507                              <1> 
  4508                              <1> ;	shl 	bl, 1 
  4509                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4510                              <1> ;		; AL = lock value (0 or process number)
  4511                              <1> ;	or	al, al
  4512                              <1> ;	jz	short @f
  4513                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4514                              <1> ;	jne	short sysstty_15
  4515                              <1> ;		; only the owner can clear its video page
  4516                              <1> ;	xor	al, al ; 0
  4517                              <1> ;@@:
  4518                              <1> ;	;mov	bl, cl		
  4519                              <1> ;	shr	bl, 1 
  4520                              <1> 
  4521 00003994 30C0                <1> 	xor	al, al	; 0
  4522 00003996 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4523                              <1> 
  4524                              <1> 	; scroll_up input:
  4525                              <1> 	;
  4526                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4527                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4528                              <1> 	; ah = attribute to be used on blanked line
  4529                              <1> 	; bl = video page number (0 to 7)
  4530                              <1> 
  4531 00003998 E8AFDBFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4532                              <1> 
  4533                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4534                              <1> 
  4535                              <1> 	; bl = video page number (0 to 7)
  4536                              <1> 	;xor	dx, dx ; column 0, row 0
  4537                              <1> 	; 02/02/2022
  4538 0000399D 31D2                <1> 	xor	edx, edx
  4539                              <1> 	; 23/02/2022
  4540                              <1> 	;call	set_cpos
  4541                              <1> 	;retn
  4542 0000399F E922DBFFFF          <1> 	jmp	set_cpos
  4543                              <1> 
  4544                              <1> 	;mov	al, bl
  4545                              <1> 	;mov	ah, [u.uno]
  4546                              <1> 	;mov	[u.r0], ax
  4547                              <1> 	;jmp	short sysstty_11
  4548                              <1> 
  4549                              <1> ;sysstty_15:
  4550                              <1> ;	; 30/01/2022
  4551                              <1> ;	; permission (denied) error
  4552                              <1> ;	;xor	dl, dl ; sysstty call sign
  4553                              <1> ;	mov	al, cl
  4554                              <1> ;	sub	ah, ah ; 0
  4555                              <1> ;	call	cttyp
  4556                              <1> ;	jmp	error
  4557                              <1> 
  4558                              <1> ; Original UNIX v1 'sysstty' routine:
  4559                              <1> ; gtty:
  4560                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4561                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4562                              <1> 	; 		/ r2 has source
  4563                              <1>         ;mov    r2,-(sp)
  4564                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4565                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4566                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4567                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4568                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4569                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4570                              <1>         ;       br .+4 / list empty, skip branch
  4571                              <1>         ;br     1b / get another character until list is empty
  4572                              <1>         ;mov    0b,r1 / move cc offset to r1
  4573                              <1>         ;inc    r1 / bump it for output clist
  4574                              <1>         ;tstb   cc(r1) / is it 0
  4575                              <1>         ;beq    1f / yes, no characters to output
  4576                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4577                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4578                              <1>         ;br     1b / try to calm it down again
  4579                              <1> ;1:
  4580                              <1>         ;mov    (sp)+,r1
  4581                              <1>         ;mov    (sp)+,r2 / restore registers
  4582                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4583                              <1>         ;beq    1f / if 0, 1f
  4584                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4585                              <1>         ;                   / control status register
  4586                              <1> ;1:
  4587                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4588                              <1>         ;beq    1f / if 0 1f
  4589                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4590                              <1> 	;		    / control status reg
  4591                              <1> ;1:
  4592                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4593                              <1>         ;jmp	sysret2 / return to user
  4594                              <1> 
  4595                              <1> sysgtty: ; < get tty status >
  4596                              <1> 	; 22/02/2022
  4597                              <1> 	; 01/02/2022
  4598                              <1> 	; 23/11/2015
  4599                              <1> 	; 29/10/2015
  4600                              <1> 	; 17/10/2015
  4601                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4602                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4603                              <1> 	;
  4604                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4605                              <1> 	; It stores in the three words addressed by it's argument
  4606                              <1> 	; the status of the typewriter whose file descriptor
  4607                              <1> 	; in (u.r0).
  4608                              <1> 	;
  4609                              <1> 	; Calling sequence:
  4610                              <1> 	;	sysgtty; arg
  4611                              <1> 	; Arguments:
  4612                              <1> 	;	arg - address of 3 words destination of the status
  4613                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4614                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4615                              <1> 	; ...............................................................
  4616                              <1> 	;	
  4617                              <1> 	; Retro UNIX 8086 v1 modification: 
  4618                              <1> 	;	'sysgtty' system call will return status of tty
  4619                              <1> 	;	(keyboard, serial port and video page status)
  4620                              <1> 	;	 in following manner:
  4621                              <1> 	;
  4622                              <1> 	; Inputs:
  4623                              <1> 	;	BX = 0 --> means 
  4624                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4625                              <1> 	;	                 for (current) process
  4626                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4627                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4628                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4629                              <1> 	;	     CH > 0 -->	tty number + 1
  4630                              <1> 	;
  4631                              <1> 	;	BX > 0 --> points to name of tty
  4632                              <1> 	;	     CL = 0 --> return keyboard status
  4633                              <1> 	;	     CL = 1 --> return video page status
  4634                              <1> 	;	     CH = undefined		 
  4635                              <1> 	;
  4636                              <1> 	; Outputs:
  4637                              <1> 	;	cf = 0 ->
  4638                              <1> 	;
  4639                              <1> 	;	     AL = tty number from 0 to 9
  4640                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4641                              <1> 	;	     AH = 0 if the tty is free/unused
  4642                              <1> 	;	     AH = the process number of the caller 
  4643                              <1>  	;	     AH = FFh if the tty is locked by another process
  4644                              <1> 	;
  4645                              <1> 	;	  (if calling is for serial port status)
  4646                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4647                              <1> 	;		  (BH = modem status, BL = Line status)
  4648                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4649                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4650                              <1> 	;
  4651                              <1> 	;	  (if calling is for keyboard status)
  4652                              <1> 	;	     BX = current character in tty/keyboard buffer
  4653                              <1> 	;		  (BH = scan code, BL = ascii code)
  4654                              <1> 	;		  (BX=0 if there is not a waiting character)
  4655                              <1> 	;	     CX  is undefined
  4656                              <1> 	;
  4657                              <1> 	;	  (if calling is for video page status)	
  4658                              <1> 	;	     BX = cursor position on the video page
  4659                              <1> 	;		  if tty number < 8
  4660                              <1> 	;		  (BH = row, BL = column)
  4661                              <1> 	;	     CX = current character (in cursor position)
  4662                              <1> 	;		  on the video page of the tty 
  4663                              <1> 	;		  if tty number < 8
  4664                              <1> 	;		  (CH = color, CL = character)
  4665                              <1> 	;	
  4666                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4667                              <1> 	;
  4668                              <1> 	;	     AH = FFh if the caller is not owner of
  4669                              <1> 	;		  specified tty or console tty
  4670                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4671                              <1> 	;	     BX, CX are undefined if cf = 1
  4672                              <1> 	;
  4673                              <1> 	;	  (If tty number is 8 or 9)
  4674                              <1> 	;	     AL = tty number 
  4675                              <1> 	;	     AH = the process number of the caller 
  4676                              <1> 	;	     BX = serial port status
  4677                              <1> 	;  		 (BH = modem status, BL = Line status)
  4678                              <1> 	;	     CX = 0
  4679                              <1> 	;
  4680                              <1> 		
  4681                              <1> gtty:   ; get (requested) tty number
  4682                              <1> 	; 22/02/2022
  4683                              <1> 	; 01/02/2022
  4684                              <1> 	; 17/10/2015
  4685                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4686                              <1> 	; 30/05/2013 - 12/07/2014
  4687                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4688                              <1> 	;
  4689                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4690                              <1> 	;
  4691                              <1> 	; 28/06/2015 (32 bit modifications)
  4692                              <1> 	; 16/01/2014
  4693 000039A4 31C0                <1> 	xor 	eax, eax
  4694 000039A6 6648                <1> 	dec	ax ; 17/10/2015
  4695 000039A8 A3[C8660000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4696 000039AD 80F901              <1> 	cmp	cl, 1
  4697 000039B0 760F                <1> 	jna	short sysgtty_0
  4698                              <1> sysgtty_invp:
  4699                              <1> 	; 28/06/2015
  4700 000039B2 C705[17670000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4700 000039BA 0000                <1>
  4701 000039BC E947F8FFFF          <1> 	jmp	error
  4702                              <1> sysgtty_0:	
  4703 000039C1 21DB                <1> 	and	ebx, ebx
  4704 000039C3 742E                <1> 	jz	short sysgtty_1
  4705                              <1> 	;
  4706 000039C5 891D[E0660000]      <1> 	mov	[u.namep], ebx
  4707                              <1> 	;push	cx ; 23/11/2015
  4708                              <1> 	; 01/02/2022
  4709 000039CB 51                  <1> 	push	ecx
  4710 000039CC E838070000          <1> 	call	namei
  4711                              <1> 	; 01/02/2022
  4712 000039D1 59                  <1> 	pop	ecx
  4713                              <1> 	;pop	cx ; 23/11/2015
  4714 000039D2 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4715                              <1> 	;
  4716 000039D4 6683F801            <1> 	cmp	ax, 1
  4717 000039D8 7622                <1> 	jna	short sysgtty_2
  4718                              <1> 	; 01/02/2022
  4719 000039DA 20E4                <1> 	and	ah, ah
  4720 000039DC 7506                <1> 	jnz	short sysgtty_inv_dn
  4721                              <1> 	;sub	ax, 10
  4722 000039DE 2C0A                <1> 	sub	al, 10
  4723 000039E0 3C09                <1> 	cmp	al, 9
  4724                              <1> 	;cmp	ax, 9
  4725                              <1> 	;ja	short sysgtty_inv_dn
  4726                              <1> 	;mov	ch, al
  4727                              <1> 	;jmp	short sysgtty_4
  4728                              <1> 	; 23/11/2015
  4729 000039E2 7629                <1> 	jna	short sysgtty_4
  4730                              <1> sysgtty_inv_dn: 
  4731                              <1> 	; 28/06/2015
  4732                              <1> 	; Invalid device name (not a tty) ! error
  4733                              <1> 	; (Device is not a tty or device name not found)
  4734 000039E4 C705[17670000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4734 000039EC 0000                <1>
  4735 000039EE E915F8FFFF          <1> 	jmp	error 
  4736                              <1> sysgtty_1:
  4737                              <1> 	; 16/01/2014
  4738 000039F3 80FD0A              <1> 	cmp	ch, 10
  4739 000039F6 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4740 000039F8 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4741 000039FA 790F                <1> 	jns	short sysgtty_3 ; not negative
  4742                              <1> 	;
  4743                              <1> sysgtty_2:
  4744                              <1> 	; get tty number of console tty
  4745 000039FC 8A25[11670000]      <1> 	mov	ah, [u.uno]
  4746                              <1>  	; 28/06/2015
  4747 00003A02 0FB6DC              <1> 	movzx 	ebx, ah
  4748 00003A05 8AAB[23640000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4749                              <1> sysgtty_3:
  4750 00003A0B 88E8                <1> 	mov	al, ch
  4751                              <1> sysgtty_4:
  4752 00003A0D A2[C8660000]        <1> 	mov	[u.r0], al
  4753                              <1>  	; 28/06/2015
  4754                              <1> 	;cmp	al, 9
  4755                              <1> 	;ja	short sysgtty_invp
  4756 00003A12 8B2D[C4660000]      <1> 	mov	ebp, [u.usp]
  4757                              <1> 	; 23/11/2015
  4758 00003A18 20C9                <1> 	and	cl, cl
  4759 00003A1A 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4760 00003A1C 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4761 00003A1E 722E                <1> 	jb	short sysgtty_6 ; video page status
  4762                              <1> 	; serial port status
  4763                              <1> 	; 12/07/2014
  4764                              <1> 	;mov	dx, 0
  4765                              <1> 	;je	short sysgtty_5
  4766                              <1> 	;inc	dl
  4767                              <1> ;sysgtty_5:
  4768                              <1> 	; 28/06/2015
  4769 00003A20 2C08                <1> 	sub	al, 8
  4770 00003A22 E894F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4771                              <1> 	; AL = Line status, AH = Modem status
  4772 00003A27 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4773 00003A2B 8A25[11670000]      <1> 	mov	ah, [u.uno]
  4774 00003A31 8825[C9660000]      <1>         mov     [u.r0+1], ah
  4775 00003A37 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4776                              <1> 				; (in ECX)
  4777 00003A3D A880                <1> 	test	al, 80h
  4778 00003A3F 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4779 00003A41 A801                <1> 	test	al, 1
  4780                              <1> 	;jz	sysret
  4781 00003A43 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4782 00003A45 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4783                              <1> sysgtty_10:
  4784 00003A49 E9DAF7FFFF          <1> 	jmp	sysret
  4785                              <1> sysgtty_6:
  4786 00003A4E A2[16670000]        <1> 	mov	[u.ttyn], al ; tty number
  4787                              <1> 	;movzx	ebx, al
  4788 00003A53 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4789 00003A55 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4790                              <1> 	; 22/04/2014 - 29/06/2015
  4791 00003A57 81C3[54630000]      <1>         add     ebx, ttyl
  4792 00003A5D 8A23                <1>  	mov	ah, [ebx]
  4793 00003A5F 3A25[11670000]      <1> 	cmp	ah, [u.uno]
  4794 00003A65 7404                <1> 	je	short sysgtty_7
  4795 00003A67 20E4                <1> 	and	ah, ah
  4796                              <1> 	;jz	short sysgtty_7
  4797 00003A69 7506                <1> 	jnz	short sysgtty_8
  4798                              <1> 	;mov	ah, 0FFh
  4799                              <1> sysgtty_7:
  4800 00003A6B 8825[C9660000]      <1>         mov     [u.r0+1], ah
  4801                              <1> sysgtty_8:
  4802 00003A71 08C9                <1> 	or	cl, cl
  4803 00003A73 7510                <1> 	jnz	short sysgtty_9
  4804 00003A75 B001                <1> 	mov	al, 1  ; test a key is available
  4805 00003A77 E8DD1C0000          <1> 	call	getc
  4806 00003A7C 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4807 00003A80 E9A3F7FFFF          <1> 	jmp	sysret
  4808                              <1> sysgtty_9:
  4809 00003A85 8A1D[16670000]      <1> 	mov	bl, [u.ttyn]
  4810                              <1> 	; bl = video page number
  4811 00003A8B E83A1E0000          <1> 	call 	get_cpos
  4812                              <1> 	; dx = cursor position
  4813 00003A90 66895510            <1> 	mov	[ebp+16], dx ; bx
  4814                              <1> 	;mov	bl, [u.ttyn]
  4815                              <1> 	; bl = video page number
  4816 00003A94 E8421E0000          <1> 	call	read_ac_current
  4817                              <1> 	; ax = character and attribute/color
  4818 00003A99 66894518            <1> 	mov	[ebp+24], ax ; cx
  4819 00003A9D E986F7FFFF          <1> 	jmp	sysret
  4820                              <1> sysgtty_dnr_err:
  4821                              <1> 	; 'device not responding !' error	
  4822                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4823 00003AA2 C705[17670000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4823 00003AAA 0000                <1>
  4824 00003AAC E957F7FFFF          <1> 	jmp	error	
  4825                              <1> 
  4826                              <1> ; Original UNIX v1 'sysgtty' routine:
  4827                              <1> ; sysgtty:
  4828                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4829                              <1> 	;	       / r2 has destination
  4830                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4831                              <1> 	;                     / in 1st word of dest
  4832                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4833                              <1> 	;                     / in 2nd word of dest
  4834                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4835                              <1>         ;jmp    sysret2 / return to user
  4836                              <1> 	
  4837                              <1> ; Original UNIX v1 'gtty' routine:
  4838                              <1> ; gtty:
  4839                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4840                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4841                              <1>         ;jsr    r0,getf / get the i-number of the file
  4842                              <1>         ;tst    r1 / is it open for reading
  4843                              <1>         ;bgt    1f / yes
  4844                              <1>         ;neg    r1 / no, i-number is negative, 
  4845                              <1> 	;          / so make it positive
  4846                              <1> ;1:
  4847                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4848                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4849                              <1>         ;bhis   error9 / no, error
  4850                              <1>         ;asl    r1 / 0%2
  4851                              <1>         ;asl    r1 / 0%4 / yes
  4852                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4853                              <1> 	;	       ; / tty block
  4854                              <1>         ;mov    u.off,r2 / put argument in r2
  4855                              <1>         ;rts    r0 / return
  2050                                  %include 'u2.s'        ; 11/05/2015
  2051                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS2.INC
  2052                              <1> ; Last Modification: 15/05/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 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2063                              <1> ;
  2064                              <1> ; ****************************************************************************
  2065                              <1> ; 03/01/2016
  2066                              <1> 
  2067                              <1> syslink:
  2068                              <1> 	; 03/02/2022
  2069                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2070                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2071                              <1> 	;
  2072                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2073                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2074                              <1> 	; given to the entry that will go in the current directory.
  2075                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2076                              <1> 	; in the name 2 entry of current directory is the same
  2077                              <1> 	; i-number for the name 1 file.
  2078                              <1> 	;
  2079                              <1> 	; Calling sequence:
  2080                              <1> 	;	syslink; name 1; name 2
  2081                              <1> 	; Arguments:
  2082                              <1> 	;	name 1 - file name to which link will be created.
  2083                              <1> 	;	name 2 - name of entry in current directory that
  2084                              <1> 	;		 links to name 1.
  2085                              <1> 	; Inputs: -
  2086                              <1> 	; Outputs: -
  2087                              <1> 	; ...............................................................
  2088                              <1> 	;	
  2089                              <1> 	; Retro UNIX 8086 v1 modification: 
  2090                              <1> 	;       'syslink' system call has two arguments; so,
  2091                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2092                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2093                              <1> 	;
  2094                              <1> 		; / name1, name2
  2095                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2096 00003AB1 891D[E0660000]      <1> 	mov	[u.namep], ebx
  2097 00003AB7 51                  <1> 	push	ecx
  2098 00003AB8 E84C060000          <1> 	call	namei
  2099                              <1> 		; jsr r0,namei / find the i-number associated with
  2100                              <1> 			     ; / the 1st path name
  2101                              <1>      	;;and	ax, ax
  2102                              <1> 	;;jz	error ; File not found
  2103                              <1> 	;jc	error 
  2104                              <1> 		; br error9 / cannot be found
  2105 00003ABD 730F                <1> 	jnc	short syslink0
  2106                              <1> 	;pop 	ecx
  2107                              <1> 	; 'file not found !' error
  2108 00003ABF C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2108 00003AC7 0000                <1>
  2109 00003AC9 E93AF7FFFF          <1> 	jmp	error
  2110                              <1> syslink0:
  2111 00003ACE E84B0E0000          <1> 	call	iget
  2112                              <1> 		; jsr r0,iget / get the i-node into core
  2113 00003AD3 8F05[E0660000]      <1> 	pop	dword [u.namep] ; ecx
  2114                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2115                              <1> 	; 03/02/2022
  2116 00003AD9 50                  <1> 	push	eax
  2117                              <1> 	;push	ax
  2118                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2119                              <1> 			    ; / (a link to this file is to be created)
  2120 00003ADA 66FF35[AC660000]    <1> 	push	word [cdev]
  2121                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2122 00003AE1 E852000000          <1> 	call	isdir
  2123                              <1> 		; jsr r0,isdir / is it a directory
  2124 00003AE6 E81E060000          <1> 	call	namei
  2125                              <1> 		; jsr r0,namei / no, get i-number of name2
  2126                              <1> 	;jnc	error
  2127                              <1> 		; br .+4   / not found 
  2128                              <1> 			 ; / so r1 = i-number of current directory
  2129                              <1> 			 ; / ii = i-number of current directory
  2130                              <1> 		; br error9 / file already exists., error
  2131 00003AEB 720F                <1> 	jc	short syslink1
  2132                              <1> 	; pop ax
  2133                              <1> 	; pop ax
  2134                              <1> 	; 'file exists !' error
  2135 00003AED C705[17670000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2135 00003AF5 0000                <1>
  2136 00003AF7 E90CF7FFFF          <1> 	jmp	error
  2137                              <1> syslink1:
  2138 00003AFC 6659                <1> 	pop	cx
  2139                              <1> 	;cmp	cx, [cdev]
  2140 00003AFE 3A0D[AC660000]      <1> 	cmp	cl, [cdev]
  2141                              <1> 	;jne	error
  2142                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2143                              <1> 			       ; / end of current directory
  2144                              <1> 	        ; bne error9
  2145 00003B04 740F                <1> 	je	short syslink2
  2146                              <1> 	; 'not same drive !' error
  2147 00003B06 C705[17670000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2147 00003B0E 0000                <1>
  2148 00003B10 E9F3F6FFFF          <1> 	jmp	error
  2149                              <1> syslink2:
  2150                              <1> 	;pop	ax
  2151                              <1> 	;push	ax
  2152                              <1> 	; 03/02/2022
  2153                              <1> 	;mov	eax, [esp]
  2154 00003B15 58                  <1> 	pop	eax
  2155 00003B16 50                  <1> 	push	eax
  2156 00003B17 66A3[FA660000]      <1> 	mov	[u.dirbuf], ax
  2157                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2158 00003B1D E89E000000          <1> 	call	mkdir
  2159                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2160                              <1> 		 	     ; / in current directory
  2161                              <1> 	; 03/02/2022
  2162 00003B22 58                  <1> 	pop	eax
  2163                              <1> 	;pop	ax
  2164                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2165 00003B23 E8F60D0000          <1> 	call	iget
  2166                              <1> 		; jsr r0,iget / get i-node into core
  2167 00003B28 FE05[C6630000]      <1> 	inc	byte [i.nlks]
  2168                              <1> 		; incb i.nlks / add 1 to its number of links
  2169 00003B2E E8F50E0000          <1> 	call	setimod
  2170                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2171 00003B33 E9F0F6FFFF          <1> 	jmp	sysret
  2172                              <1> 
  2173                              <1> isdir:
  2174                              <1> 	; 03/02/2022
  2175                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2176                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2177                              <1> 	;
  2178                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2179                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2180                              <1> 	;  called by syslink and sysunlink to make sure directories
  2181                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2182                              <1> 	; 'isdir' does not bother checking. The current i-node
  2183                              <1> 	;  is not disturbed.			
  2184                              <1> 	;		
  2185                              <1> 	; INPUTS ->
  2186                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2187                              <1> 	;    u.uid - user id
  2188                              <1> 	; OUTPUTS ->
  2189                              <1> 	;    r1 - contains current i-number upon exit
  2190                              <1> 	;    	 (current i-node back in core) 
  2191                              <1> 	;	
  2192                              <1> 	; ((AX = R1))
  2193                              <1> 	;
  2194                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2195                              <1> 	;
  2196                              <1> 
  2197                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2198                              <1> 	; / there is an error unless super user made the call
  2199                              <1> 	
  2200 00003B38 803D[0E670000]00    <1> 	cmp	byte [u.uid], 0 
  2201                              <1> 		; tstb u.uid / super user
  2202 00003B3F 762B                <1> 	jna	short isdir1
  2203                              <1> 		; beq 1f / yes, don't care
  2204 00003B41 66FF35[A8660000]    <1> 	push	word [ii]
  2205                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2206 00003B48 E8D10D0000          <1> 	call	iget
  2207                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2208                              <1> 	; 03/02/2022
  2209 00003B4D F605[C5630000]40    <1> 	test	byte [i.flgs+1], 40h
  2210                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2211                              <1> 		; bit $40000,i.flgs / is it a directory
  2212                              <1> 	;jnz	error
  2213                              <1> 		; bne error9 / yes, error
  2214 00003B54 740F                <1> 	jz	short isdir0
  2215 00003B56 C705[17670000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2215 00003B5E 0000                <1>
  2216                              <1> 				; 'permission denied !' error
  2217                              <1> 	;pop	ax
  2218 00003B60 E9A3F6FFFF          <1> 	jmp	error	
  2219                              <1> isdir0:	
  2220 00003B65 6658                <1> 	pop	ax
  2221                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2222 00003B67 E8B20D0000          <1> 	call	iget
  2223                              <1> 		; jsr r0,iget / get it back in
  2224                              <1> isdir1: ; 1:
  2225 00003B6C C3                  <1> 	retn
  2226                              <1> 		; rts r0
  2227                              <1> 
  2228                              <1> sysunlink:
  2229                              <1> 	; 03/02/2022
  2230                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2231                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2232                              <1> 	;
  2233                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2234                              <1> 	; name from its directory. If this entry was the last link
  2235                              <1> 	; to the file, the contents of the file are freed and the
  2236                              <1> 	; file is destroyed. If, however, the file was open in any
  2237                              <1> 	; process, the actual destruction is delayed until it is 
  2238                              <1> 	; closed, even though the directory entry has disappeared.
  2239                              <1> 	; 
  2240                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2241                              <1> 	; does not exist or that its directory can not be written.
  2242                              <1> 	; Write permission is not required on the file itself.
  2243                              <1> 	; It is also illegal to unlink a directory (except for
  2244                              <1> 	; the superuser).
  2245                              <1> 	;
  2246                              <1> 	; Calling sequence:
  2247                              <1> 	;	sysunlink; name
  2248                              <1> 	; Arguments:
  2249                              <1> 	;	name - name of directory entry to be removed 
  2250                              <1> 	; Inputs: -
  2251                              <1> 	; Outputs: -
  2252                              <1> 	; ...............................................................
  2253                              <1> 	;				
  2254                              <1> 	; Retro UNIX 8086 v1 modification:
  2255                              <1> 	;	 The user/application program puts address of the name
  2256                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2257                              <1> 
  2258                              <1> 	; / name - remove link name
  2259 00003B6D 891D[E0660000]      <1> 	mov	[u.namep], ebx
  2260                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2261 00003B73 E891050000          <1> 	call	namei
  2262                              <1> 		; jsr r0,namei / find the i-number associated 
  2263                              <1> 			     ; / with the path name
  2264                              <1> 	;jc	error
  2265                              <1> 		; br error9 / not found
  2266 00003B78 730F                <1> 	jnc	short sysunlink1
  2267                              <1> 	; 'file not found !' error
  2268 00003B7A C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2268 00003B82 0000                <1>
  2269 00003B84 E97FF6FFFF          <1> 	jmp	error
  2270                              <1> sysunlink1:
  2271                              <1> 	; 03/02/2022
  2272 00003B89 50                  <1> 	push	eax
  2273                              <1> 	;push	ax
  2274                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2275 00003B8A E8A9FFFFFF          <1> 	call	isdir
  2276                              <1> 		; jsr r0,isdir / is it a directory
  2277                              <1> 	;xor 	ax, ax
  2278                              <1> 	; 03/02/2022
  2279 00003B8F 31C0                <1> 	xor	eax, eax
  2280 00003B91 66A3[FA660000]      <1> 	mov	[u.dirbuf], ax ; 0
  2281                              <1> 		; clr u.dirbuf / no, clear the location that will
  2282                              <1> 			   ; / get written into the i-number portion
  2283                              <1> 			 ; / of the entry
  2284 00003B97 832D[E4660000]0A    <1> 	sub	dword [u.off], 10
  2285                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2286 00003B9E E865000000          <1> 	call	wdir
  2287                              <1> 		; jsr r0,wdir / free the directory entry
  2288                              <1> 	; 03/02/2022
  2289 00003BA3 58                  <1> 	pop	eax
  2290                              <1> 	;pop	ax
  2291                              <1> 		; mov (sp)+,r1 / get i-number back
  2292 00003BA4 E8750D0000          <1> 	call	iget
  2293                              <1> 		; jsr r0,iget / get i-node
  2294 00003BA9 E87A0E0000          <1> 	call	setimod
  2295                              <1> 		; jsr r0,setimod / set modified flag
  2296 00003BAE FE0D[C6630000]      <1> 	dec	byte [i.nlks]
  2297                              <1> 		; decb i.nlks / decrement the number of links
  2298                              <1> 	;jnz	sysret
  2299                              <1> 		; bgt sysret9 / if this was not the last link
  2300                              <1> 			    ; / to file return
  2301                              <1> 	; 03/02/2022
  2302 00003BB4 7505                <1> 	jnz	short sysunlink2
  2303                              <1> 	; AX = r1 = i-number
  2304 00003BB6 E8B8090000          <1> 	call	anyi
  2305                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2306                              <1> 			 ; / Then free contents of file and destroy it.
  2307                              <1> sysunlink2:
  2308 00003BBB E968F6FFFF          <1> 	jmp	sysret
  2309                              <1> 		; br sysret9
  2310                              <1> 
  2311                              <1> mkdir:
  2312                              <1> 	; 03/02/2022
  2313                              <1> 	; 12/10/2015
  2314                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2315                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2316                              <1> 	;
  2317                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2318                              <1> 	; by u.namep into the current directory.
  2319                              <1> 	;
  2320                              <1> 	; INPUTS ->
  2321                              <1> 	;    u.namep - points to a file name 
  2322                              <1> 	;	           that is about to be a directory entry.
  2323                              <1> 	;    ii - current directory's i-number.	
  2324                              <1> 	; OUTPUTS ->
  2325                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2326                              <1> 	;    u.off - points to entry to be filled 
  2327                              <1> 	;	     in the current directory		
  2328                              <1> 	;    u.base - points to start of u.dirbuf.
  2329                              <1> 	;    r1 - contains i-number of current directory 
  2330                              <1> 	;	
  2331                              <1> 	; ((AX = R1)) output
  2332                              <1> 	;
  2333                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2334                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2335                              <1> 	;
  2336                              <1> 
  2337                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2338 00003BC0 31C0                <1> 	xor 	eax, eax
  2339 00003BC2 BF[FC660000]        <1>         mov     edi, u.dirbuf+2
  2340 00003BC7 89FE                <1> 	mov	esi, edi
  2341 00003BC9 AB                  <1> 	stosd
  2342 00003BCA AB                  <1> 	stosd
  2343                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2344 00003BCB 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2345                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2346                              <1> 	;mov 	ebp, [u.namep]
  2347 00003BCD E8B9060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2348                              <1> 		; esi = physical address (page start + offset)
  2349                              <1> 		; ecx = byte count in the page (1 - 4096)
  2350                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2351                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2352                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2353                              <1> mkdir_1: ; 1: 
  2354 00003BD2 45                  <1> 	inc	ebp ; 12/10/2015
  2355                              <1> 	;
  2356                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2357                              <1> 	 ; 01/08/2013
  2358 00003BD3 AC                  <1> 	lodsb
  2359                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2360 00003BD4 20C0                <1> 	and 	al, al
  2361 00003BD6 7426                <1> 	jz 	short mkdir_3 	  
  2362                              <1> 		; beq 1f / if null, done
  2363 00003BD8 3C2F                <1> 	cmp	al, '/'
  2364                              <1> 		; cmp r1,$'/ / is it a "/"?
  2365 00003BDA 7413                <1> 	je	short mkdir_err
  2366                              <1> 	;je	error
  2367                              <1> 		; beq error9 / yes, error
  2368                              <1> 	; 03/02/2022
  2369 00003BDC 49                  <1> 	dec	ecx
  2370                              <1> 	; 12/10/2015
  2371                              <1> 	;dec	cx
  2372 00003BDD 7505                <1> 	jnz	short mkdir_2
  2373                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2374 00003BDF E8AD060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2375                              <1> 		; esi = physical address (page start + offset)
  2376                              <1> 		; ecx = byte count in the page
  2377                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2378                              <1> mkdir_2:
  2379 00003BE4 81FF[04670000]      <1> 	cmp     edi, u.dirbuf+10
  2380                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2381                              <1> 				     ; / a char?
  2382 00003BEA 74E6                <1> 	je	short mkdir_1
  2383                              <1> 		; beq 1b / yes, go back
  2384 00003BEC AA                  <1> 	stosb
  2385                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2386 00003BED EBE3                <1> 	jmp 	short mkdir_1
  2387                              <1> 		; br 1b / get next char
  2388                              <1> mkdir_err:
  2389                              <1> 	; 17/06/2015
  2390 00003BEF C705[17670000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2390 00003BF7 0000                <1>
  2391 00003BF9 E90AF6FFFF          <1> 	jmp	error
  2392                              <1> mkdir_3: ; 1:
  2393 00003BFE A1[DC660000]        <1> 	mov	eax, [u.dirp]
  2394 00003C03 A3[E4660000]        <1> 	mov	[u.off], eax
  2395                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2396                              <1> 				 ; / slot to u.off
  2397                              <1> wdir: 	; 03/02/2022
  2398                              <1> 	; 29/04/2013
  2399 00003C08 C705[E8660000]-     <1>         mov     dword [u.base], u.dirbuf
  2399 00003C0E [FA660000]          <1>
  2400                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2401 00003C12 C705[EC660000]0A00- <1>         mov     dword [u.count], 10
  2401 00003C1A 0000                <1>
  2402                              <1> 		; mov $10.,u.count / u.count = 10
  2403 00003C1C 66A1[A8660000]      <1> 	mov	ax, [ii] 
  2404                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2405 00003C22 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2406 00003C24 E8C90D0000          <1> 	call 	access
  2407                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2408                              <1> 				 ; / for writing
  2409                              <1> 	; AX = i-number of current directory
  2410                              <1> 	; 01/08/2013
  2411 00003C29 FE05[29670000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2412                              <1> 	;call	writei
  2413                              <1> 	;	; jsr r0,writei / write into directory
  2414                              <1> 	;retn	
  2415                              <1> 	;	; rts r0
  2416                              <1> 	; 03/02/2022
  2417 00003C2F E9AC100000          <1> 	jmp	writei
  2418                              <1> 
  2419                              <1> sysexec:
  2420                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2421                              <1> 	; 03/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18)
  2422                              <1> 	; 23/10/2015
  2423                              <1> 	; 19/10/2015
  2424                              <1> 	; 10/10/2015, 18/10/2015
  2425                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2426                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2427                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2428                              <1> 	; 24/06/2015, 25/06/2015
  2429                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2430                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2431                              <1> 	;
  2432                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2433                              <1> 	; pointed to by 'name' in the sysexec call. 
  2434                              <1> 	; 'sysexec' performs the following operations:
  2435                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2436                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2437                              <1> 	;    3. sets trap vectors to system routines.
  2438                              <1> 	;    4. loads arguments to be passed to executing file into
  2439                              <1> 	;	highest locations of user's core
  2440                              <1> 	;    5. puts pointers to arguments in locations immediately
  2441                              <1> 	;	following arguments.
  2442                              <1> 	;    6.	saves number of arguments in next location.
  2443                              <1> 	;    7. intializes user's stack area so that all registers
  2444                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2445                              <1> 	;	to core when 'sysret' restores registers 
  2446                              <1> 	;	and does an rti.
  2447                              <1> 	;    8. inializes u.r0 and u.sp
  2448                              <1> 	;    9. zeros user's core down to u.r0
  2449                              <1> 	;   10.	reads executable file from storage device into core
  2450                              <1> 	;	starting at location 'core'.
  2451                              <1> 	;   11.	sets u.break to point to end of user's code with
  2452                              <1> 	;	data area appended.
  2453                              <1> 	;   12.	calls 'sysret' which returns control at location
  2454                              <1> 	;	'core' via 'rti' instruction. 		  		
  2455                              <1> 	;
  2456                              <1> 	; Calling sequence:
  2457                              <1> 	;	sysexec; namep; argp
  2458                              <1> 	; Arguments:
  2459                              <1> 	;	namep - points to pathname of file to be executed
  2460                              <1> 	;	argp  - address of table of argument pointers
  2461                              <1> 	;	argp1... argpn - table of argument pointers
  2462                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2463                              <1> 	; Inputs: (arguments)
  2464                              <1> 	; Outputs: -	
  2465                              <1> 	; ...............................................................
  2466                              <1> 	;
  2467                              <1> 	; Retro UNIX 386 v1 modification: 
  2468                              <1> 	;	User application runs in it's own virtual space 
  2469                              <1> 	;	which is izolated from kernel memory (and other
  2470                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2471                              <1> 	;	privilige mode. Virtual start address is always 0.
  2472                              <1> 	;	User's core memory starts at linear address 400000h
  2473                              <1> 	;	(the end of the 1st 4MB).
  2474                              <1> 	;
  2475                              <1> 	; Retro UNIX 8086 v1 modification: 
  2476                              <1> 	;	user/application segment and system/kernel segment
  2477                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2478                              <1> 	;	are different (user's registers are saved to 
  2479                              <1> 	;	and then restored from system's stack.)
  2480                              <1> 	;
  2481                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2482                              <1> 	;	      arguments which were in these registers;
  2483                              <1> 	;	      but, it returns by putting the 1st argument
  2484                              <1> 	;	      in 'u.namep' and the 2nd argument
  2485                              <1> 	;	      on top of stack. (1st argument is offset of the
  2486                              <1> 	;	      file/path name in the user's program segment.)		 	
  2487                              <1> 	
  2488                              <1> 	;call	arg2
  2489                              <1> 	; * name - 'u.namep' points to address of file/path name
  2490                              <1> 	;          in the user's program segment ('u.segmnt')
  2491                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2492                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2493                              <1> 	;          which is on top of stack.
  2494                              <1> 	;
  2495                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2496                              <1> 
  2497                              <1> 	; 23/06/2015 (32 bit modifications)
  2498                              <1> 
  2499 00003C34 891D[E0660000]      <1> 	mov	[u.namep], ebx ; argument 1
  2500                              <1>         ; 18/10/2015
  2501 00003C3A 890D[40670000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2502 00003C40 E8C4040000          <1> 	call	namei
  2503                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2504                              <1> 			     ; / named in sysexec call in r1
  2505                              <1> 	;jc	error
  2506                              <1> 		; br error9
  2507 00003C45 731E                <1> 	jnc	short sysexec_0
  2508                              <1> 	;
  2509                              <1> 	; 'file not found !' error
  2510 00003C47 C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2510 00003C4F 0000                <1>
  2511 00003C51 E9B2F5FFFF          <1> 	jmp	error 
  2512                              <1> sysexec_not_exf:
  2513                              <1> 	; 'not executable file !' error
  2514 00003C56 C705[17670000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2514 00003C5E 0000                <1>
  2515 00003C60 E9A3F5FFFF          <1> 	jmp	error 
  2516                              <1> sysexec_0:
  2517 00003C65 E8B40C0000          <1> 	call	iget
  2518                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2519                              <1> 	; 03/02/2022
  2520 00003C6A F605[C4630000]10    <1> 	test	byte [i.flgs], 10h
  2521                              <1>         ;test	word [i.flgs], 10h
  2522                              <1> 		; bit $20,i.flgs / is file executable
  2523 00003C71 74E3                <1> 	jz	short sysexec_not_exf
  2524                              <1> 	;jz	error
  2525                              <1> 		; beq error9
  2526                              <1> 	;;
  2527 00003C73 E800150000          <1> 	call	iopen
  2528                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2529                              <1> 			     ; / given in r1 (opens file)
  2530                              <1> 	; AX = i-number of the file
  2531                              <1> 	; 03/02/2022
  2532 00003C78 F605[C4630000]20    <1> 	test	byte [i.flgs], 20h
  2533                              <1> 	;test	word [i.flgs], 20h
  2534                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2535 00003C7F 7415                <1> 	jz	short sysexec_1
  2536                              <1> 		; beq 1f
  2537 00003C81 803D[0E670000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2538                              <1> 		; tstb u.uid / test user id
  2539 00003C88 760C                <1> 	jna	short sysexec_1
  2540                              <1> 		; beq 1f / super user
  2541 00003C8A 8A0D[C7630000]      <1> 	mov	cl, [i.uid]
  2542 00003C90 880D[0E670000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2543                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2544                              <1> 				 ; / as process user id
  2545                              <1> sysexec_1:
  2546                              <1> 	; 03/02/2022
  2547                              <1> 	; 18/10/2215
  2548                              <1> 	; 10/10/2015
  2549                              <1> 	; 21/07/2015, 24/07/2015
  2550                              <1> 	; 24/06/2015, 25/06/2015
  2551                              <1>         ; Moving arguments to the end of [u.upage]
  2552                              <1> 	; (by regarding page borders in user's memory space)
  2553                              <1> 	;
  2554                              <1> 	; 10/10/2015
  2555                              <1> 	; 21/07/2015
  2556 00003C96 89E5                <1> 	mov	ebp, esp ; (**)
  2557                              <1> 	; 18/10/2015
  2558 00003C98 89EF                <1> 	mov 	edi, ebp
  2559 00003C9A B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2560                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2561 00003C9F 29CF                <1> 	sub	edi, ecx
  2562 00003CA1 89FC                <1> 	mov	esp, edi
  2563 00003CA3 31C0                <1> 	xor	eax, eax
  2564 00003CA5 A3[F0660000]        <1> 	mov 	[u.nread], eax ; 0
  2565                              <1> 	; 03/02/2022
  2566                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2567                              <1> 	; may leave it with any value after an error))
  2568                              <1> 	;mov	[argc], ax
  2569 00003CAA A2[3E670000]        <1> 	mov	[argc], al ; 0
  2570                              <1> 	;
  2571 00003CAF 49                  <1> 	dec	ecx ; 256 - 1
  2572 00003CB0 890D[EC660000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2573                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2574                              <1> sysexec_2:
  2575 00003CB6 8B35[40670000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2576 00003CBC E864020000          <1> 	call	get_argp
  2577                              <1> 	;mov	ecx, 4 
  2578                              <1> 	; 03/02/2022
  2579 00003CC1 31C9                <1> 	xor	ecx, ecx
  2580 00003CC3 B104                <1> 	mov	cl, 4
  2581                              <1> sysexec_3:
  2582 00003CC5 21C0                <1> 	and	eax, eax
  2583 00003CC7 7456                <1> 	jz	short sysexec_6
  2584                              <1> 	; 18/10/2015
  2585 00003CC9 010D[40670000]      <1> 	add	[argv], ecx ; 4
  2586 00003CCF 66FF05[3E670000]    <1> 	inc	word [argc]
  2587                              <1> 	;
  2588 00003CD6 A3[E8660000]        <1> 	mov	[u.base], eax
  2589                              <1>  	; 23/10/2015
  2590 00003CDB 66C705[27670000]00- <1> 	mov	word [u.pcount], 0
  2590 00003CE3 00                  <1>
  2591                              <1> sysexec_4:
  2592 00003CE4 E821120000          <1> 	call	cpass ; get a character from user's core memory
  2593 00003CE9 750B                <1>         jnz	short sysexec_5
  2594                              <1> 		; (max. 255 chars + null)
  2595                              <1> 	; 18/10/2015
  2596 00003CEB 28C0                <1> 	sub 	al, al
  2597 00003CED AA                  <1> 	stosb
  2598 00003CEE FF05[F0660000]      <1> 	inc	dword [u.nread]
  2599 00003CF4 EB29                <1> 	jmp	short sysexec_6
  2600                              <1> sysexec_5:
  2601 00003CF6 AA                  <1> 	stosb
  2602 00003CF7 20C0                <1> 	and 	al, al
  2603 00003CF9 75E9                <1> 	jnz	short sysexec_4
  2604                              <1> 	;mov	ecx, 4
  2605                              <1> 	; 03/02/2022
  2606 00003CFB 29C9                <1> 	sub	ecx, ecx
  2607 00003CFD B104                <1> 	mov	cl, 4
  2608                              <1> 	;cmp	[ncount], ecx ; 4
  2609                              <1> 	; 03/02/2022
  2610 00003CFF 66390D[3C670000]    <1> 	cmp	[ncount], cx ; 4
  2611 00003D06 72AE                <1> 	jb	short sysexec_2
  2612 00003D08 8B35[38670000]      <1> 	mov	esi, [nbase]
  2613 00003D0E 010D[38670000]      <1> 	add	[nbase], ecx ; 4	
  2614 00003D14 66290D[3C670000]    <1> 	sub	[ncount], cx 
  2615 00003D1B 8B06                <1> 	mov	eax, [esi]
  2616 00003D1D EBA6                <1> 	jmp	short sysexec_3
  2617                              <1> sysexec_6:
  2618                              <1> 	; 18/10/2015
  2619                              <1> 	; argument list transfer from user's core memory to
  2620                              <1> 	; kernel stack frame is OK here.
  2621                              <1> 	; [u.nread] = ; argument list length
  2622                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2623                              <1> 	;
  2624                              <1> 	; 18/10/2015
  2625                              <1>         ; 21/07/2015, 24/07/2015
  2626                              <1> 	; 25/06/2015, 02/07/2015
  2627                              <1> 	; 23/06/2015, 24/06/2015
  2628                              <1> 	;
  2629 00003D1F 8B1D[1F670000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2630 00003D25 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2631 00003D27 740A                <1> 	jz	short sysexec_7
  2632 00003D29 A1[1B670000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2633 00003D2E E8FEE8FFFF          <1> 	call	deallocate_page_dir
  2634                              <1> sysexec_7:
  2635 00003D33 E82EE8FFFF          <1> 	call	make_page_dir
  2636                              <1> 	;jc	short sysexec_14
  2637                              <1> 	;jc	panic  ; allocation error 
  2638                              <1> 		       ; after a deallocation would be nonsence !?
  2639                              <1> 	; 03/02/2022
  2640 00003D38 7243                <1> 	jc	short sysexec_panic
  2641                              <1> 
  2642                              <1> 	; 24/07/2015
  2643                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2644                              <1> 	;     of the user's page directory
  2645                              <1> 	;     (It is needed for interrupts!)
  2646                              <1> 	; 18/10/2015
  2647 00003D3A 8B15[08630000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2648 00003D40 8B02                <1> 	mov	eax, [edx] ; physical address of
  2649                              <1> 			   ; kernel's first page table (1st 4 MB)
  2650                              <1> 			   ; (PDE 0 of kernel's page directory)
  2651 00003D42 8B15[1B670000]      <1> 	mov 	edx, [u.pgdir]
  2652 00003D48 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2653                              <1> 	;
  2654                              <1> 	; 20/07/2015
  2655 00003D4A BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2656                              <1> 	; 18/10/2015
  2657 00003D4F BE[30670000]        <1> 	mov	esi, pcore ; physical start address
  2658                              <1> sysexec_8:	
  2659 00003D54 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2660 00003D59 E826E8FFFF          <1> 	call	make_page_table
  2661                              <1> 	;jc	panic
  2662                              <1> 	; 03/02/2022
  2663 00003D5E 721D                <1> 	jc	short sysexec_panic
  2664                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2665 00003D60 E82DE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2666                              <1> 	;jc	panic
  2667                              <1> 	; 03/02/2022
  2668 00003D65 7216                <1> 	jc	short sysexec_panic
  2669                              <1> 	;
  2670 00003D67 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2671                              <1> 	; ebx = virtual address (24/07/2015)
  2672                              <1> 	; 03/02/2022
  2673                              <1> 	;call 	add_to_swap_queue
  2674                              <1> 	; 18/10/2015
  2675 00003D69 81FE[34670000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2676 00003D6F 7411                <1> 	je	short sysexec_9 ; yes
  2677 00003D71 BE[34670000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2678                              <1> 	; 20/07/2015
  2679 00003D76 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2680                              <1> 	; ebx = virtual end address + segment base address - 4K
  2681 00003D7B EBD7                <1>         jmp     short sysexec_8
  2682                              <1> 
  2683                              <1> sysexec_panic:
  2684                              <1> 	; 03/02/2022
  2685 00003D7D E945EDFFFF          <1> 	jmp	panic
  2686                              <1> 
  2687                              <1> sysexec_9:
  2688                              <1> 	; 18/10/2015
  2689                              <1> 	; 26/08/2015
  2690                              <1> 	; 25/06/2015
  2691                              <1> 	; move arguments from kernel stack to [ecore]
  2692                              <1> 	; (argument list/line will be copied from kernel stack
  2693                              <1> 	; frame to the last (stack) page of user's core memory)
  2694                              <1> 	; 18/10/2015
  2695 00003D82 8B3D[34670000]      <1> 	mov	edi, [ecore]
  2696 00003D88 81C700100000        <1> 	add	edi, PAGE_SIZE
  2697                              <1> 	;movzx	eax, word [argc]
  2698                              <1> 	; 03/02/2022
  2699 00003D8E 31C0                <1> 	xor	eax, eax
  2700 00003D90 A0[3E670000]        <1> 	mov	al, [argc]
  2701 00003D95 08C0                <1> 	or	al, al
  2702                              <1> 	;or	eax, eax
  2703 00003D97 7509                <1> 	jnz	short sysexec_10
  2704 00003D99 89FB                <1> 	mov 	ebx, edi
  2705 00003D9B 83EB04              <1> 	sub	ebx, 4 
  2706 00003D9E 8903                <1> 	mov	[ebx], eax ; 0
  2707 00003DA0 EB43                <1> 	jmp 	short sysexec_13
  2708                              <1> sysexec_10:
  2709 00003DA2 8B0D[F0660000]      <1> 	mov	ecx, [u.nread]
  2710                              <1> 	;mov 	esi, [argv]
  2711 00003DA8 89E6                <1> 	mov	esi, esp ; start address of argument list
  2712 00003DAA 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2713                              <1> 	
  2714                              <1> 	;;;;
  2715                              <1> 	; 09/05/2022
  2716                              <1> 	; (move edi -backward- to dword boundary)
  2717                              <1> 	; ((this will prevent 'general protection fault' error
  2718                              <1> 	;  as result of a lodsd or dword move instruction
  2719                              <1> 	;  at the end of argument list))
  2720 00003DAC 83EF03              <1> 	sub	edi, 3
  2721 00003DAF 83E7FC              <1> 	and	edi, ~3 ; (*)
  2722                              <1> 	;;;
  2723                              <1> 
  2724 00003DB2 89C2                <1> 	mov	edx, eax
  2725                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2726 00003DB4 FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2727 00003DB6 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2728                              <1> 	; edx <= 128
  2729 00003DB9 89FB                <1> 	mov	ebx, edi
  2730                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2731                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2732 00003DBB 29D3                <1> 	sub 	ebx, edx
  2733 00003DBD 89FA                <1> 	mov	edx, edi
  2734 00003DBF F3A4                <1> 	rep	movsb
  2735 00003DC1 89D6                <1> 	mov 	esi, edx
  2736 00003DC3 89DF                <1> 	mov 	edi, ebx
  2737 00003DC5 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2738 00003DCA 2B15[34670000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2739 00003DD0 AB                  <1> 	stosd	; eax = argument count	
  2740                              <1> sysexec_11:
  2741 00003DD1 89F0                <1> 	mov	eax, esi
  2742 00003DD3 01D0                <1> 	add	eax, edx
  2743 00003DD5 AB                  <1> 	stosd  ; eax = virtual address
  2744 00003DD6 FE0D[3E670000]      <1> 	dec	byte [argc]
  2745 00003DDC 7407                <1> 	jz	short sysexec_13
  2746                              <1> sysexec_12:
  2747 00003DDE AC                  <1> 	lodsb
  2748 00003DDF 20C0                <1> 	and	al, al
  2749 00003DE1 75FB                <1> 	jnz	short sysexec_12
  2750 00003DE3 EBEC                <1> 	jmp	short sysexec_11
  2751                              <1> 	;
  2752                              <1> 	; 1:
  2753                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2754                              <1> 			     ; / pointers to arguments to be passed
  2755                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2756                              <1> 			      ; / u.quit = 1 take quit
  2757                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2758                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2759                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2760                              <1> 			       ; / system routine
  2761                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2762                              <1> 			       ; / set to take system routine
  2763                              <1> 		; mov $sstack,sp / stack space used during swapping
  2764                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2765                              <1> 		; mov $ecore,r5 / r5 has end of core
  2766                              <1> 		; mov $core,r4 / r4 has start of users core
  2767                              <1> 		; mov r4,u.base / u.base has start of users core
  2768                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2769                              <1> 	; 1:
  2770                              <1> 		; tst (r2)+ / argument char = "nul"
  2771                              <1> 		; bne 1b
  2772                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2773                              <1> 			  ; / end of argument pointer list
  2774                              <1> 	; 1:
  2775                              <1> 	     ; / move arguments to bottom of users core
  2776                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2777                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2778                              <1> 			    ; / ptr list
  2779                              <1> 		; blo 1f / branch to 1f when all arguments
  2780                              <1> 		       ; / are moved
  2781                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2782                              <1> 	; 2:
  2783                              <1> 		; tstb (r3)+
  2784                              <1> 		; bne 2b / scan argument for \0 (nul)
  2785                              <1> 
  2786                              <1> 	; 2:
  2787                              <1> 		; movb -(r3),-(r5) / move argument char 
  2788                              <1> 				 ; / by char starting at "ecore"
  2789                              <1> 		; cmp r3,(r2) / moved all characters in 
  2790                              <1> 			    ; / this argument
  2791                              <1> 		; bhi 2b / branch 2b if not
  2792                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2793                              <1> 			     ; / r5 has pointer to nth arg
  2794                              <1> 		; br 1b / string
  2795                              <1> 	; 1:
  2796                              <1> 		; clrb -(r5)
  2797                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2798                              <1> 			 ; / last word of argument strings
  2799                              <1> 		; mov $core,r2
  2800                              <1> 	
  2801                              <1> 	; 1: / move argument pointers into core following 
  2802                              <1> 	      ; / argument strings
  2803                              <1> 		; cmp r2,r4
  2804                              <1> 		; bhis 1f / branch to 1f when all pointers
  2805                              <1> 			; / are moved
  2806                              <1> 		; mov (r2)+,-(r5)
  2807                              <1> 		; br 1b
  2808                              <1> 	; 1:
  2809                              <1> 		; sub $core,r4 / gives number of arguments *2
  2810                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2811                              <1> 		       ; / the number of args stored
  2812                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2813                              <1> 			     ; / of the argument pointers
  2814                              <1> sysexec_13:
  2815                              <1> 	; 19/10/2015
  2816                              <1> 	; 18/10/2015
  2817                              <1> 	; 29/07/2015
  2818                              <1> 	; 24/07/2015, 25/07/2015
  2819                              <1> 	; 25/06/2015, 20/07/2015
  2820                              <1> 	; 23/06/2015, 24/06/2015
  2821                              <1> 	;
  2822                              <1> 	; moving arguments to [ecore] is OK here..
  2823                              <1> 	; 18/10/2015
  2824 00003DE5 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2825                              <1> 	; ebx = beginning addres of argument list pointers
  2826                              <1> 	;	in user's stack
  2827                              <1> 	; 19/10/2015
  2828 00003DE7 2B1D[34670000]      <1> 	sub 	ebx, [ecore]
  2829 00003DED 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2830                              <1> 			; end of core - 4096 (last page)
  2831                              <1> 			; (virtual address)
  2832 00003DF3 891D[40670000]      <1> 	mov	[argv], ebx
  2833 00003DF9 891D[F4660000]      <1> 	mov	[u.break], ebx ; available user memory
  2834                              <1> 	;
  2835 00003DFF 29C0                <1> 	sub	eax, eax
  2836 00003E01 C705[EC660000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2836 00003E09 0000                <1>
  2837                              <1> 		; mov $14,u.count
  2838 00003E0B C705[D8660000]-     <1> 	mov	dword [u.fofp], u.off
  2838 00003E11 [E4660000]          <1>
  2839                              <1> 		; mov $u.off,u.fofp
  2840 00003E15 A3[E4660000]        <1> 	mov	[u.off], eax ; 0
  2841                              <1> 		; clr u.off / set offset in file to be read to zero
  2842                              <1> 	; 25/07/2015
  2843 00003E1A A3[E8660000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2844                              <1> 	; 25/06/2015 
  2845 00003E1F 66A1[A8660000]      <1> 	mov	ax, [ii]
  2846                              <1> 	; AX = i-number of the executable file
  2847 00003E25 E8C80C0000          <1> 	call	readi
  2848                              <1> 		; jsr r0,readi / read in first six words of 
  2849                              <1> 			; / user's file, starting at $core
  2850                              <1> 		; mov sp,r5 / put users stack address in r5
  2851                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2852                              <1> 				; / from r5 (leaves number of words
  2853                              <1> 				; / less 26 available for
  2854                              <1> 			     	; / program in user core
  2855                              <1> 		; mov r5,u.count /
  2856                              <1> 	; 25/06/2015
  2857 00003E2A 8B0D[F4660000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2858 00003E30 890D[EC660000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2859                              <1> 	;
  2860 00003E36 8B0D[F0660000]      <1> 	mov	ecx, [u.nread]
  2861 00003E3C 890D[F4660000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2862 00003E42 80F920              <1> 	cmp	cl, 32
  2863 00003E45 7540                <1>         jne     short sysexec_15
  2864                              <1> 	;:
  2865                              <1> 	; 25/06/2015
  2866                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2867                              <1> 	; 18/10/2015
  2868 00003E47 8B35[30670000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2869                              <1> 		             ; (phys. start addr. of the exec. file)
  2870 00003E4D AD                  <1> 	lodsd
  2871 00003E4E 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2872 00003E52 7533                <1> 	jne	short sysexec_15
  2873                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2874                              <1> 			      ; / if file is standard a.out format
  2875                              <1> 		; bne 1f / branch, if not standard format
  2876 00003E54 AD                  <1> 	lodsd
  2877 00003E55 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2878 00003E57 AD                  <1> 	lodsd
  2879 00003E58 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2880                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2881                              <1> 		              ; / number of bytes in program text	
  2882                              <1> 		; sub $14,r5 / subtract 12
  2883 00003E5A 89CB                <1> 	mov	ebx, ecx
  2884                              <1> 	;
  2885                              <1> 	; 25/06/2015
  2886                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2887                              <1> 	;	and SINGLIX operating systems (as code template).
  2888                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2889                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2890                              <1> 	;	Overrun is not possible for current version. 	
  2891                              <1> 	;
  2892 00003E5C AD                  <1> 	lodsd	
  2893 00003E5D 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2894 00003E5F 3B1D[EC660000]      <1> 	cmp	ebx, [u.count]
  2895 00003E65 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2896                              <1> 	;
  2897                              <1> 	; 24/07/2015
  2898                              <1> 	; add bss section size to [u.break]
  2899 00003E67 0105[F4660000]      <1> 	add 	[u.break], eax
  2900                              <1> 	;
  2901 00003E6D 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2902                              <1> 	;cmp	ecx, [u.count]
  2903                              <1> 	;jnb	short sysexec_16
  2904                              <1> 		; cmp r5,u.count /
  2905                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2906 00003E70 890D[EC660000]      <1> 	mov	[u.count], ecx ; required read count
  2907                              <1> 		; mov r5,u.count
  2908                              <1> 	;
  2909 00003E76 EB2A                <1> 	jmp	short sysexec_16
  2910                              <1> 	;
  2911                              <1> sysexec_14:
  2912                              <1> 	; 23/06/2015
  2913                              <1> 	; insufficient (out of) memory
  2914 00003E78 C705[17670000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2914 00003E80 0000                <1>
  2915 00003E82 E981F3FFFF          <1> 	jmp	error
  2916                              <1> 	;
  2917                              <1> sysexec_15:
  2918                              <1> 	; 25/06/2015
  2919 00003E87 0FB715[C8630000]    <1>         movzx   edx, word [i.size] ; file size
  2920 00003E8E 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2921 00003E90 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2922 00003E92 01D1                <1> 	add	ecx, edx ; [i.size]
  2923 00003E94 3B0D[EC660000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2924 00003E9A 77DC                <1> 	ja	short sysexec_14
  2925 00003E9C 8915[EC660000]      <1> 	mov	[u.count], edx
  2926                              <1> sysexec_16:
  2927 00003EA2 66A1[A8660000]      <1> 	mov	ax, [ii] ; i-number
  2928 00003EA8 E8450C0000          <1> 	call	readi
  2929                              <1> 		; add core+10,u.nread / add size of user data area 
  2930                              <1> 		                    ; / to u.nread
  2931                              <1> 		; br 2f
  2932                              <1> 	; 1:
  2933                              <1> 		; jsr r0,readi / read in rest of file
  2934                              <1> 	; 2:
  2935 00003EAD 8B0D[F0660000]      <1> 	mov	ecx, [u.nread]
  2936 00003EB3 010D[F4660000]      <1> 	add	[u.break], ecx
  2937                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2938                              <1> 				    ; / user code
  2939                              <1> 		; add $core+14,u.break / plus data area
  2940                              <1> sysexec_17: ; 20/07/2015
  2941                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2942                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2943                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2944                              <1> 	;;mov	ax, [ii] ; i-number
  2945                              <1> 	;call	iclose
  2946                              <1> 	;	; jsr r0,iclose / does nothing
  2947 00003EB9 31C0                <1>         xor     eax, eax
  2948 00003EBB FEC0                <1> 	inc	al
  2949 00003EBD 66A3[06670000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2950 00003EC3 66A3[08670000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2951                              <1> 	; 02/07/2015
  2952 00003EC9 833D[1F670000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2953 00003ED0 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2954                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2955 00003ED2 8B15[08630000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2956 00003ED8 8915[1F670000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2957                              <1> sysexec_18:
  2958                              <1> 	; 18/10/2015
  2959                              <1> 	; 05/08/2015
  2960                              <1> 	; 29/07/2015
  2961 00003EDE 8B2D[40670000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2962                              <1> 			    ; list pointers (argument count)
  2963 00003EE4 FA                  <1> 	cli
  2964 00003EE5 8B25[A4620000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2965                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2966                              <1> 			    ; for this process	 
  2967                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2968                              <1> 	;xor	eax, eax ; 0
  2969 00003EEB FEC8                <1> 	dec	al ; eax = 0
  2970 00003EED 66BA2300            <1> 	mov	dx, UDATA
  2971 00003EF1 6652                <1> 	push	dx  ; user's stack segment
  2972 00003EF3 55                  <1> 	push	ebp ; user's stack pointer
  2973                              <1> 		    ; (points to number of arguments)
  2974 00003EF4 FB                  <1> 	sti
  2975 00003EF5 9C                  <1> 	pushfd	; EFLAGS
  2976                              <1> 		; Set IF for enabling interrupts in user mode	
  2977                              <1> 	;or	dword [esp], 200h 
  2978                              <1> 	;
  2979                              <1> 	;mov	bx, UCODE
  2980                              <1> 	;push	bx ; user's code segment
  2981 00003EF6 6A1B                <1> 	push	UCODE
  2982                              <1> 	;push	0
  2983 00003EF8 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2984                              <1> 		; clr -(r5) / popped into ps when rti in 
  2985                              <1> 			  ; / sysrele is executed
  2986                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2987                              <1> 		                ; / in sysrele is executed
  2988                              <1> 		;mov r5,0f / load second copyz argument
  2989                              <1> 		;tst -(r5) / decrement r5
  2990 00003EF9 8925[C0660000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2991                              <1> 	; 05/08/2015
  2992                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2993                              <1> 	; ('push dx' would cause to general protection fault, 
  2994                              <1> 	; after 'pop ds' etc.)
  2995                              <1> 	;
  2996                              <1> 	;; push dx ; ds (UDATA)
  2997                              <1> 	;; push dx ; es (UDATA)
  2998                              <1> 	;; push dx ; fs (UDATA)
  2999                              <1> 	;; push dx ; gs (UDATA)
  3000                              <1> 	;
  3001                              <1> 	; This is a trick to prevent general protection fault
  3002                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3003 00003EFF 8EC2                <1> 	mov 	es, dx ; UDATA
  3004 00003F01 06                  <1> 	push 	es ; ds (UDATA)
  3005 00003F02 06                  <1> 	push 	es ; es (UDATA)
  3006 00003F03 06                  <1> 	push 	es ; fs (UDATA)
  3007 00003F04 06                  <1> 	push	es ; gs (UDATA)
  3008 00003F05 66BA1000            <1> 	mov	dx, KDATA
  3009 00003F09 8EC2                <1> 	mov	es, dx
  3010                              <1> 	;
  3011                              <1> 	;; pushad simulation
  3012 00003F0B 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3013 00003F0D 50                  <1> 	push	eax ; eax (0)
  3014 00003F0E 50                  <1> 	push	eax ; ecx (0)
  3015 00003F0F 50                  <1> 	push	eax ; edx (0)
  3016 00003F10 50                  <1> 	push	eax ; ebx (0)
  3017 00003F11 55                  <1> 	push	ebp ; esp before pushad
  3018 00003F12 50                  <1> 	push	eax ; ebp (0)
  3019 00003F13 50                  <1> 	push	eax ; esi (0)		
  3020 00003F14 50                  <1> 	push	eax ; edi (0)	
  3021                              <1> 	;
  3022 00003F15 A3[C8660000]        <1> 	mov	[u.r0], eax ; eax = 0
  3023 00003F1A 8925[C4660000]      <1> 	mov	[u.usp], esp
  3024                              <1> 		; mov r5,u.r0 /
  3025                              <1> 		; sub $16.,r5 / skip 8 words
  3026                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3027                              <1> 		;             / effectively zeroes all regs
  3028                              <1> 			    ; / when sysrele is executed
  3029                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3030                              <1> 		; clr u.break
  3031                              <1> 		; mov r5,sp / point sp to user's stack
  3032                              <1> 	;
  3033 00003F20 E905F3FFFF          <1> 	jmp	sysret0
  3034                              <1> 	;jmp	sysret
  3035                              <1> 		; br sysret3 / return to core image at $core
  3036                              <1> 
  3037                              <1> get_argp:
  3038                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  3039                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3040                              <1> 	; 18/10/2015 (nbase, ncount)
  3041                              <1> 	; 21/07/2015
  3042                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3043                              <1> 	; Get (virtual) address of argument from user's core memory
  3044                              <1> 	;
  3045                              <1> 	; INPUT:
  3046                              <1> 	;	esi = virtual address of argument pointer
  3047                              <1> 	; OUTPUT:
  3048                              <1> 	;	eax = virtual address of argument
  3049                              <1> 	;
  3050                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3051                              <1> 	;
  3052 00003F25 833D[1F670000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3053                              <1> 				    ; (the caller is kernel)
  3054                              <1>         ;jna	short get_argpk
  3055                              <1> 	; 03/02/2022
  3056 00003F2C 7719                <1> 	ja	short get_argp5
  3057                              <1> get_argpk:
  3058                              <1> 	; Argument is in kernel's memory space
  3059 00003F2E 66C705[3C670000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3059 00003F36 10                  <1>
  3060 00003F37 8935[38670000]      <1> 	mov	[nbase], esi
  3061 00003F3D 8305[38670000]04    <1> 	add	dword [nbase], 4
  3062 00003F44 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3063 00003F46 C3                  <1> 	retn
  3064                              <1> get_argp5:
  3065 00003F47 89F3                <1>      	mov	ebx, esi
  3066 00003F49 E89FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3067 00003F4E 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  3068 00003F50 A3[38670000]        <1> 	mov 	[nbase], eax ; physical address	
  3069 00003F55 66890D[3C670000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3070 00003F5C B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3071                              <1> 	;cmp	cx, ax ; 4
  3072                              <1> 	; 03/02/2022
  3073 00003F61 39C1                <1> 	cmp	ecx, eax
  3074 00003F63 734C                <1> 	jnb	short get_argp2
  3075 00003F65 89F3                <1> 	mov	ebx, esi
  3076 00003F67 01CB                <1> 	add	ebx, ecx
  3077 00003F69 E87FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3078 00003F6E 7237                <1> 	jc	short get_argp_err
  3079                              <1> 	;push	esi
  3080 00003F70 89C6                <1> 	mov	esi, eax
  3081 00003F72 66870D[3C670000]    <1> 	xchg	cx, [ncount]
  3082 00003F79 8735[38670000]      <1> 	xchg	esi, [nbase]
  3083 00003F7F B504                <1> 	mov	ch, 4
  3084 00003F81 28CD                <1> 	sub	ch, cl
  3085                              <1> get_argp0:
  3086 00003F83 AC                  <1> 	lodsb
  3087                              <1> 	;push	ax
  3088                              <1> 	; 03/02/2022
  3089 00003F84 50                  <1> 	push	eax
  3090 00003F85 FEC9                <1> 	dec	cl
  3091 00003F87 75FA                <1>         jnz     short get_argp0
  3092 00003F89 8B35[38670000]      <1> 	mov	esi, [nbase]
  3093                              <1> 	; 21/07/2015
  3094 00003F8F 0FB6C5              <1> 	movzx	eax, ch
  3095 00003F92 0105[38670000]      <1> 	add	[nbase], eax
  3096 00003F98 662905[3C670000]    <1> 	sub	[ncount], ax
  3097                              <1> get_argp1:
  3098 00003F9F AC                  <1> 	lodsb
  3099 00003FA0 FECD                <1> 	dec	ch
  3100 00003FA2 7423                <1>         jz      short get_argp3
  3101                              <1>         ;push	ax
  3102                              <1> 	; 03/02/2022
  3103 00003FA4 50                  <1> 	push	eax
  3104 00003FA5 EBF8                <1> 	jmp     short get_argp1
  3105                              <1> get_argp_err:
  3106 00003FA7 A3[17670000]        <1> 	mov	[u.error], eax
  3107 00003FAC E957F2FFFF          <1> 	jmp	error
  3108                              <1> get_argp2:
  3109                              <1> 	; 21/07/2015
  3110                              <1> 	;mov	eax, 4
  3111 00003FB1 8B15[38670000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3112 00003FB7 0105[38670000]      <1> 	add	[nbase], eax
  3113 00003FBD 662905[3C670000]    <1> 	sub	[ncount], ax
  3114                              <1> 	;
  3115 00003FC4 8B02                <1> 	mov	eax, [edx]
  3116 00003FC6 C3                  <1> 	retn
  3117                              <1> get_argp3:
  3118 00003FC7 B103                <1> 	mov	cl, 3
  3119                              <1> get_argp4:
  3120 00003FC9 C1E008              <1> 	shl	eax, 8
  3121                              <1> 	;pop	dx
  3122                              <1> 	; 03/02/2022
  3123 00003FCC 5A                  <1> 	pop	edx
  3124 00003FCD 88D0                <1> 	mov 	al, dl
  3125 00003FCF E2F8                <1>         loop    get_argp4
  3126                              <1> 	;pop	esi
  3127 00003FD1 C3                  <1> 	retn	
  3128                              <1> 
  3129                              <1> sysfstat:
  3130                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3131                              <1> 	;	([idev] return in eax)
  3132                              <1> 	;	0 = root device
  3133                              <1> 	;	1 = mounted device (>0)
  3134                              <1> 	; 03/02/2022
  3135                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3136                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3137                              <1> 	;
  3138                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3139                              <1> 	; on open files instead of files given by name. It puts the
  3140                              <1> 	; buffer address on the stack, gets the i-number and
  3141                              <1> 	; checks to see if the file is open for reading or writing.
  3142                              <1> 	; If the file is open for writing (i-number is negative)
  3143                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3144                              <1> 	; is made.	
  3145                              <1> 	;
  3146                              <1> 	; Calling sequence:
  3147                              <1> 	;	sysfstat; buf
  3148                              <1> 	; Arguments:
  3149                              <1> 	;	buf - buffer address
  3150                              <1> 	;
  3151                              <1> 	; Inputs: *u.r0 - file descriptor
  3152                              <1> 	; Outputs: buffer is loaded with file information
  3153                              <1> 	; ...............................................................
  3154                              <1> 	;				
  3155                              <1> 	; Retro UNIX 8086 v1 modification:
  3156                              <1> 	;       'sysfstat' system call has two arguments; so,
  3157                              <1> 	;	* 1st argument, file descriptor is in BX register
  3158                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3159                              <1> 
  3160                              <1> 	; / set status of open file
  3161                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3162 00003FD2 51                  <1> 	push	ecx
  3163                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3164                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3165                              <1> 		; jsr r0,getf / get the files i-number
  3166                              <1> 	; BX = file descriptor (file number)
  3167 00003FD3 E8FE000000          <1> 	call	getf1
  3168                              <1> 	; 03/02/2022
  3169 00003FD8 21C0                <1> 	and	eax, eax
  3170                              <1> 	;and	ax, ax ; i-number of the file
  3171                              <1> 		; tst	r1 / is it 0?
  3172                              <1> 	;jz	error
  3173                              <1> 		; beq error3 / yes, error
  3174 00003FDA 750F                <1> 	jnz	short sysfstat1
  3175 00003FDC C705[17670000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3175 00003FE4 0000                <1>
  3176 00003FE6 E91DF2FFFF          <1> 	jmp	error
  3177                              <1> sysfstat1:
  3178 00003FEB 80FC80              <1> 	cmp	ah, 80h
  3179 00003FEE 7222                <1>         jb      short sysstat1
  3180                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3181 00003FF0 66F7D8              <1> 	neg	ax
  3182                              <1> 		; neg r1 / make it positive, then branch
  3183 00003FF3 EB1D                <1> 	jmp	short sysstat1
  3184                              <1> 		; br 1f / to 1f
  3185                              <1> sysstat:
  3186                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3187                              <1> 	;	([idev] return in eax)
  3188                              <1> 	;	0 = root device
  3189                              <1> 	;	1 = mounted device (>0)
  3190                              <1> 	; 03/02/2022
  3191                              <1> 	; 18/10/2015
  3192                              <1> 	; 07/10/2015
  3193                              <1> 	; 02/09/2015
  3194                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3195                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3196                              <1> 	;
  3197                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3198                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3199                              <1> 	; long and information about the file placed in it.	
  3200                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3201                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3202                              <1> 	; is then loaded and the results are given in the UNIX
  3203                              <1> 	; Programmers Manual sysstat (II).	
  3204                              <1> 	;
  3205                              <1> 	; Calling sequence:
  3206                              <1> 	;	sysstat; name; buf
  3207                              <1> 	; Arguments:
  3208                              <1> 	;	name - points to the name of the file
  3209                              <1> 	;	buf - address of a 34 bytes buffer
  3210                              <1> 	; Inputs: -
  3211                              <1> 	; Outputs: buffer is loaded with file information
  3212                              <1> 	; ...............................................................
  3213                              <1> 	;				
  3214                              <1> 	; Retro UNIX 8086 v1 modification: 
  3215                              <1> 	;       'sysstat' system call has two arguments; so,
  3216                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3217                              <1> 	;	to get sysstat system call arguments from the user;
  3218                              <1> 	;	* 1st argument, name is pointed to by BX register
  3219                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3220                              <1> 	;
  3221                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3222                              <1> 	;	      arguments which were in these registers;
  3223                              <1> 	;	      but, it returns by putting the 1st argument
  3224                              <1> 	;	      in 'u.namep' and the 2nd argument
  3225                              <1> 	;	      on top of stack. (1st argument is offset of the
  3226                              <1> 	;	      file/path name in the user's program segment.)		 	
  3227                              <1> 	
  3228                              <1> 	; / ; name of file; buffer - get files status
  3229                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3230 00003FF5 891D[E0660000]      <1> 	mov	[u.namep], ebx
  3231 00003FFB 51                  <1> 	push	ecx
  3232 00003FFC E808010000          <1> 	call	namei
  3233                              <1> 		; jsr r0,namei / get the i-number for the file
  3234                              <1> 	;jc	error
  3235                              <1> 		; br error3 / no such file, error
  3236 00004001 730F                <1> 	jnc	short sysstat1
  3237                              <1> 	; pop 	ecx
  3238                              <1> sysstat_err0:
  3239                              <1> 	; 'file not found !' error
  3240 00004003 C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3240 0000400B 0000                <1>
  3241 0000400D E9F6F1FFFF          <1> 	jmp	error
  3242                              <1> 
  3243                              <1> ;statx: db 0
  3244                              <1> 
  3245                              <1> sysstat1: ; 1:
  3246 00004012 E807090000          <1> 	call	iget
  3247                              <1> 		; jsr r0,iget / get the i-node into core
  3248                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3249                              <1> 	; 02/09/2015
  3250 00004017 8F05[E8660000]      <1> 	pop	dword [u.base]
  3251                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3252 0000401D E861000000          <1> 	call	sysstat_gpa ; get physical address
  3253 00004022 730A                <1> 	jnc 	short sysstat2
  3254                              <1> sysstat_err1:
  3255 00004024 A3[17670000]        <1> 	mov	dword [u.error], eax ; error code
  3256 00004029 E9DAF1FFFF          <1> 	jmp	error
  3257                              <1> sysstat2:
  3258 0000402E A0[A8660000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3259 00004033 AA                  <1> 	stosb
  3260 00004034 FF05[E8660000]      <1> 	inc 	dword [u.base]
  3261                              <1> 	;dec 	cx
  3262                              <1> 	; 03/02/2022
  3263 0000403A 49                  <1> 	dec	ecx
  3264 0000403B 7505                <1> 	jnz	short sysstat3
  3265 0000403D E841000000          <1> 	call	sysstat_gpa
  3266                              <1> 	;jc	short sysstat_err1
  3267                              <1> sysstat3:
  3268 00004042 A0[A9660000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3269 00004047 AA                  <1> 	stosb
  3270                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3271 00004048 FF05[E8660000]      <1> 	inc 	dword [u.base]
  3272                              <1> 	;;dec 	word [u.pcount]
  3273                              <1> 	;dec	cx
  3274                              <1> 	; 03/02/2022
  3275 0000404E 49                  <1> 	dec	ecx
  3276 0000404F 7505                <1> 	jnz	short sysstat4
  3277 00004051 E82D000000          <1> 	call	sysstat_gpa
  3278                              <1> 	;jc	short sysstat_err1	
  3279                              <1> sysstat4:
  3280 00004056 BE[C4630000]        <1> 	mov	esi, inode
  3281                              <1> 		; mov $inode,r2 / r2 points to i-node
  3282                              <1> sysstat5: ; 1:
  3283 0000405B A4                  <1> 	movsb
  3284                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3285 0000405C FF05[E8660000]      <1> 	inc 	dword [u.base]
  3286                              <1> 	;;dec 	word [u.pcount]
  3287                              <1> 	;dec	cx
  3288                              <1> 	; 03/02/2022
  3289 00004062 49                  <1> 	dec	ecx
  3290 00004063 7505                <1> 	jnz	short sysstat6
  3291 00004065 E819000000          <1> 	call	sysstat_gpa
  3292                              <1> 	;jc	short sysstat_err1
  3293                              <1> sysstat6:		
  3294 0000406A 81FE[E4630000]      <1> 	cmp	esi, inode + 32
  3295                              <1> 		; cmp r2,$inode+32 / done?
  3296 00004070 75E9                <1> 	jne	short sysstat5
  3297                              <1> 		; bne 1b / no, go back
  3298                              <1> 
  3299                              <1> 	;;;
  3300                              <1> 	; 09/05/2022
  3301                              <1> 	;*** additional feature *** -retro unix only- 
  3302                              <1> 	;
  3303                              <1> 	; !! return device number -of current inode- in eax !!
  3304                              <1> 	;
  3305                              <1> 	; (modification reason/purpose:
  3306                              <1> 	; to improve 'pwd' command's pathname output/result
  3307                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3308                              <1> 	; error due to same inode numbers in root file system
  3309                              <1> 	; and mounted file system.)
  3310                              <1> 	;
  3311 00004072 29C0                <1> 	sub	eax, eax
  3312 00004074 A0[AA660000]        <1> 	mov	al, [idev] ; [cdev]
  3313 00004079 A3[C8660000]        <1> 	mov	[u.r0], eax
  3314                              <1> 	;;;  
  3315                              <1> 
  3316 0000407E E9A5F1FFFF          <1> 	jmp	sysret
  3317                              <1> 		; br sysret3 / return through sysret
  3318                              <1> 	;
  3319                              <1> sysstat_gpa: ; get physical address of file status buffer
  3320                              <1> 	; 02/09/2015
  3321 00004083 8B1D[E8660000]      <1> 	mov 	ebx, [u.base]
  3322                              <1> 	; 07/10/2015
  3323 00004089 E85FE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3324                              <1> 	;jc	short sysstat_gpa1
  3325 0000408E 7294                <1> 	jc	short sysstat_err1
  3326                              <1> 	; 18/10/2015
  3327 00004090 89C7                <1> 	mov	edi, eax ; physical address
  3328                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3329                              <1> ;sysstat_gpa1:
  3330 00004092 C3                  <1> 	retn
  3331                              <1> 
  3332                              <1> fclose:
  3333                              <1> 	; 03/02/2022
  3334                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3335                              <1> 	;            (32 bit offset pointer modification)
  3336                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3337                              <1> 	;
  3338                              <1> 	; Given the file descriptor (index to the u.fp list)
  3339                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3340                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3341                              <1> 	; u.fp list is cleared. If all the processes that opened
  3342                              <1> 	; that file close it, then fsp etry is freed and the file
  3343                              <1> 	; is closed. If not a return is taken. 
  3344                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3345                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3346                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3347                              <1> 	; a check is made to see if the file is special.	
  3348                              <1> 	;
  3349                              <1> 	; INPUTS ->
  3350                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3351                              <1> 	;    u.fp - list of entries in the fsp table
  3352                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3353                              <1> 	; OUTPUTS ->
  3354                              <1> 	;    r1 - contains the same file descriptor
  3355                              <1> 	;    r2 - contains i-number
  3356                              <1> 	;
  3357                              <1> 	; ((AX = R1))
  3358                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3359                              <1> 	;
  3360                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3361                              <1> 	;              if i-number of the file is 0. (error)  	
  3362                              <1> 
  3363                              <1> 	;movzx	edx, ax ; **
  3364                              <1> 	; 03/02/2022
  3365                              <1> 	;movzx	edx, al
  3366 00004093 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3367 00004095 50                  <1> 	push	eax ; ***
  3368                              <1> 	;push	ax ; ***
  3369                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3370                              <1> 			     ; / the index to u.fp list)
  3371 00004096 E839000000          <1> 	call	getf
  3372                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3373                              <1> 			    ; / cdev has device =, u.fofp 
  3374                              <1> 			    ; / points to 3rd word of fsp entry
  3375 0000409B 6683F801            <1> 	cmp	ax, 1 ; r1
  3376                              <1> 		; tst r1 / is i-number 0?
  3377 0000409F 7231                <1> 	jb	short fclose_2
  3378                              <1> 		; beq 1f / yes, i-node not active so return
  3379                              <1> 		; tst (r0)+ / no, jump over error return
  3380 000040A1 89D3                <1> 	mov	ebx, edx ; **
  3381                              <1> 	; 03/02/2022
  3382 000040A3 89C2                <1> 	mov	edx, eax ; *
  3383                              <1> 	;mov 	dx, ax ; *
  3384                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3385                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3386                              <1> 			    ; / which is index to u.fp ; **
  3387 000040A5 C683[CE660000]00    <1> 	mov	byte [ebx+u.fp], 0
  3388                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3389 000040AC 8B1D[D8660000]      <1> 	mov	ebx, [u.fofp]
  3390                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3391                              <1> fclose_0:
  3392 000040B2 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3393                              <1> 		; decb 2(r1) / decrement the number of processes 
  3394                              <1> 			   ; / that have opened the file
  3395 000040B5 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3396                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3397                              <1> 	;
  3398                              <1> 	; 03/02/2022
  3399 000040B7 52                  <1> 	push	edx ; *
  3400                              <1> 	;push	dx ; *
  3401                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3402                              <1> 	;xor	ax, ax ; 0
  3403                              <1> 	; 03/02/2022
  3404 000040B8 31C0                <1> 	xor	eax, eax
  3405 000040BA 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3406                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3407 000040BE 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3408                              <1> 		; tstb	3(r1) / has this file been deleted
  3409 000040C1 20C0                <1> 	and	al, al
  3410 000040C3 7407                <1> 	jz	short fclose_1
  3411                              <1> 		; beq 2f / no, branch
  3412                              <1> 	; 03/02/2022
  3413 000040C5 89D0                <1> 	mov	eax, edx
  3414                              <1> 	;mov	ax, dx ; *
  3415                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3416                              <1> 	; AX = inode number
  3417 000040C7 E8A7040000          <1> 	call	anyi
  3418                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3419                              <1> 			    ; / check if file appears in fsp again
  3420                              <1> fclose_1: ; 2:
  3421                              <1> 	; 03/02/2022
  3422 000040CC 58                  <1> 	pop	eax ; * 
  3423                              <1> 	;pop	ax ; *
  3424                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3425 000040CD E8E5110000          <1> 	call	iclose ; close if it is special file 
  3426                              <1> 		; jsr r0,iclose / check to see if its a special file
  3427                              <1> fclose_2: ; 1:
  3428                              <1> 	; 03/02/2022
  3429 000040D2 58                  <1> 	pop	eax ; ***
  3430                              <1> 	;pop	ax ; ***
  3431                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3432 000040D3 C3                  <1> 	retn
  3433                              <1> 		; rts r0
  3434                              <1> 
  3435                              <1> getf:	; / get the device number and the i-number of an open file
  3436                              <1> 	; 03/02/2022
  3437                              <1> 	; 13/05/2015
  3438                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3439                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3440                              <1> 	;
  3441 000040D4 89C3                <1> 	mov	ebx, eax
  3442                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3443                              <1> 	; 03/02/2022
  3444 000040D6 29C0                <1> 	sub	eax, eax
  3445                              <1> 	;
  3446 000040D8 83FB0A              <1> 	cmp	ebx, 10
  3447                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3448 000040DB 732B                <1>         jnb	short getf2 ; 13/05/2015
  3449                              <1> 	;jnb	error
  3450                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3451                              <1> 			    ; / index in fsp table
  3452                              <1> 	; 03/02/2022
  3453 000040DD 8A83[CE660000]      <1> 	mov	al, [ebx+u.fp]
  3454                              <1> 	;mov	bl, [ebx+u.fp]
  3455                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3456                              <1> 		                  ; / in fsp table
  3457                              <1> 	; 03/02/2022
  3458 000040E3 08C0                <1> 	or	al, al
  3459 000040E5 7421                <1> 	jz	short getf2
  3460                              <1> 	;or	bl, bl
  3461                              <1> 	;jnz	short getf3
  3462                              <1> 	;;jz	short getf4
  3463                              <1> 		; beq 1f / if its zero return
  3464                              <1> ;getf2:
  3465                              <1> ;	; 'File not open !' error (ax=0)
  3466                              <1> ;	sub	eax, eax
  3467                              <1> ;	retn
  3468                              <1> 
  3469                              <1> getf3:	
  3470                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3471                              <1> 	;
  3472                              <1> 	; 'fsp' table (10 bytes/entry)
  3473                              <1> 	; bit 15				   bit 0
  3474                              <1> 	; ---|-------------------------------------------
  3475                              <1> 	; r/w|		i-number of open file
  3476                              <1> 	; ---|-------------------------------------------
  3477                              <1> 	;		   device number
  3478                              <1> 	; -----------------------------------------------
  3479                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3480                              <1> 	; -----------------------------------------------
  3481                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3482                              <1> 	; ----------------------|------------------------
  3483                              <1> 	;  flag that says file 	| number of processes
  3484                              <1> 	;   has been deleted	| that have file open 
  3485                              <1> 	; ----------------------|------------------------
  3486                              <1> 	;
  3487                              <1> 	;mov	eax, 10
  3488                              <1> 	; 03/02/2022
  3489 000040E7 B30A                <1> 	mov	bl, 10
  3490 000040E9 F6E3                <1> 	mul	bl
  3491 000040EB BB[8E640000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3492 000040F0 01C3                <1> 	add	ebx, eax
  3493                              <1> 		; asl r1
  3494                              <1> 		; asl r1 / multiply by 8 to get index into 
  3495                              <1> 		       ; / fsp table entry
  3496                              <1> 		; asl r1
  3497                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3498                              <1> 			      ; / in the fsp entry
  3499 000040F2 891D[D8660000]      <1> 	mov	[u.fofp], ebx
  3500                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3501                              <1> 			      ; / in fsp entry in u.fofp
  3502 000040F8 4B                  <1> 	dec	ebx
  3503 000040F9 4B                  <1> 	dec	ebx
  3504                              <1> 	;mov	al, [ebx]
  3505 000040FA 668B03              <1> 	mov	ax, [ebx]
  3506                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3507 000040FD 66A3[AC660000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3508                              <1> 			     ;;dev number is in 1 byte
  3509                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3510 00004103 4B                  <1> 	dec	ebx
  3511 00004104 4B                  <1> 	dec	ebx
  3512 00004105 668B03              <1> 	mov	ax, [ebx]
  3513                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3514                              <1> getf2:	; 03/02/2022
  3515                              <1> getf4:	; 1:
  3516 00004108 C3                  <1> 	retn
  3517                              <1> 		; rts r0
  3518                              <1> 
  3519                              <1> namei:
  3520                              <1> 	; 15/05/2022
  3521                              <1> 	; 14/05/2022 (mounted directory path, '..' method)
  3522                              <1> 	; 03/02/2022
  3523                              <1> 	; 18/10/2015 (nbase, ncount)
  3524                              <1> 	; 12/10/2015
  3525                              <1> 	; 21/08/2015
  3526                              <1> 	; 18/07/2015
  3527                              <1> 	; 02/07/2015
  3528                              <1> 	; 17/06/2015
  3529                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3530                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3531                              <1> 	;
  3532                              <1> 	; 'namei' takes a file path name and returns i-number of
  3533                              <1> 	; the file in the current directory or the root directory
  3534                              <1> 	; (if the first character of the pathname is '/').	
  3535                              <1> 	;
  3536                              <1> 	; INPUTS ->
  3537                              <1> 	;    u.namep - points to a file path name
  3538                              <1> 	;    u.cdir - i-number of users directory
  3539                              <1> 	;    u.cdev - device number on which user directory resides	
  3540                              <1> 	; OUTPUTS ->
  3541                              <1> 	;    r1 - i-number of file
  3542                              <1> 	;    cdev
  3543                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3544                              <1> 	;               occurs in the search for file path name.
  3545                              <1> 	;	        If no match u.dirb points to the end of 
  3546                              <1> 	;               the directory and r1 = i-number of the current
  3547                              <1> 	;	        directory.	
  3548                              <1> 	; ((AX = R1))
  3549                              <1> 	;
  3550                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3551                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3552                              <1> 	;
  3553                              <1> 
  3554 00004109 66A1[CC660000]      <1> 	mov	ax, [u.cdir]
  3555                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3556                              <1> 			      ; / in r1
  3557 0000410F 668B15[0C670000]    <1> 	mov	dx, [u.cdrv]
  3558 00004116 668915[AC660000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3559                              <1> 				    ; device/drive number is in 1 byte, 
  3560                              <1> 				    ; not in 1 word!
  3561                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3562                              <1> 				; / into cdev
  3563                              <1> 	; 12/10/2015
  3564                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3565                              <1>       	 ; convert virtual (pathname) addr to physical address
  3566 0000411D E869010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3567                              <1> 		; esi = physical address of [u.namep]
  3568                              <1> 		; ecx = byte count in the page
  3569 00004122 803E2F              <1> 	cmp	byte [esi], '/'
  3570                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3571 00004125 751D                <1> 	jne	short namei_1
  3572                              <1> 		; bne 1f
  3573 00004127 FF05[E0660000]      <1> 	inc	dword [u.namep]
  3574                              <1> 		; inc u.namep / go to next char
  3575                              <1> 	; 03/02/2022
  3576 0000412D 49                  <1> 	dec	ecx
  3577                              <1> 	;dec	cx ; remain byte count in the page
  3578 0000412E 7506                <1> 	jnz	short namei_0
  3579                              <1> 	; 12/10/2015
  3580 00004130 E856010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3581                              <1> 		; esi = physical address (page start + offset)
  3582                              <1> 		; ecx = byte count in the page
  3583 00004135 4E                  <1> 	dec	esi
  3584                              <1> namei_0:
  3585 00004136 46                  <1> 	inc 	esi  ; go to next char
  3586 00004137 66A1[B8660000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3587                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3588 0000413D C605[AC660000]00    <1> 	mov	byte [cdev], 0
  3589                              <1> 		; clr cdev / clear device number
  3590                              <1> namei_1: ; 1:
  3591 00004144 F606FF              <1> 	test	byte [esi], 0FFh
  3592                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3593 00004147 74BF                <1> 	jz	short getf4
  3594                              <1> 	;jz	nig
  3595                              <1> 		; tstb *u.namep / is the character in file name a nul
  3596                              <1> 		; beq nig / yes, end of file name reached; 
  3597                              <1> 			; / branch to "nig"
  3598                              <1> namei_2: ; 1:
  3599                              <1> 	; 18/10/2015
  3600 00004149 8935[38670000]      <1> 	mov 	[nbase], esi
  3601 0000414F 66890D[3C670000]    <1> 	mov 	[ncount], cx
  3602                              <1> 	;
  3603                              <1> 	;mov	dx, 2
  3604 00004156 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3605 00004158 E895080000          <1> 	call	access
  3606                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3607                              <1> 	; 'access' will not return here if user has not "r" permission !
  3608                              <1> 	; 03/02/2022
  3609 0000415D F605[C5630000]40    <1> 	test	byte [i.flgs+1], 40h
  3610                              <1> 	;test 	word [i.flgs], 4000h
  3611                              <1> 		; bit $40000,i.flgs / directory i-node?
  3612 00004164 746A                <1>         jz      short namei_err
  3613                              <1> 		; beq error3 / no, got an error
  3614                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3615 00004166 31C0                <1> 	xor	eax, eax
  3616 00004168 A3[E4660000]        <1> 	mov	[u.off], eax ; 0
  3617 0000416D 66A1[C8630000]      <1> 	mov	ax, [i.size]
  3618 00004173 A3[DC660000]        <1> 	mov	[u.dirp], eax
  3619                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3620                              <1> 		; clr u.off / u.off is file offset used by user
  3621 00004178 C705[D8660000]-     <1> 	mov	dword [u.fofp], u.off
  3621 0000417E [E4660000]          <1>
  3622                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3623                              <1> 				  ; / the offset portion of fsp entry
  3624                              <1> namei_3: ; 2:
  3625 00004182 C705[E8660000]-     <1> 	mov	dword [u.base], u.dirbuf
  3625 00004188 [FA660000]          <1>
  3626                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3627                              <1> 				    ; / copied from a directory
  3628 0000418C C705[EC660000]0A00- <1> 	mov 	dword [u.count], 10 	
  3628 00004194 0000                <1>
  3629                              <1>  		; mov $10.,u.count / u.count is byte count 
  3630                              <1> 				 ; / for reads and writes
  3631 00004196 66A1[A8660000]      <1> 	mov 	ax, [ii]
  3632                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3633 0000419C FE05[29670000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3634 000041A2 E84B090000          <1>     	call	readi
  3635                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3636                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3637 000041A7 8B0D[F0660000]      <1> 	mov 	ecx, [u.nread]
  3638 000041AD 09C9                <1> 	or 	ecx, ecx
  3639                              <1> 		; tst u.nread
  3640 000041AF 741B                <1> 	jz	short nib
  3641                              <1> 		; ble nib / gives error return
  3642                              <1> 	;
  3643 000041B1 668B1D[FA660000]    <1> 	mov 	bx, [u.dirbuf]
  3644 000041B8 6621DB              <1> 	and 	bx, bx       
  3645                              <1> 		; tst u.dirbuf /
  3646 000041BB 7522                <1> 	jnz	short namei_4
  3647                              <1> 		; bne 3f / branch when active directory entry 
  3648                              <1> 		       ; / (i-node word in entry non zero)
  3649 000041BD A1[E4660000]        <1> 	mov	eax, [u.off]
  3650 000041C2 83E80A              <1> 	sub	eax, 10
  3651 000041C5 A3[DC660000]        <1> 	mov	[u.dirp], eax
  3652                              <1> 		; mov u.off,u.dirp
  3653                              <1> 		; sub $10.,u.dirp
  3654 000041CA EBB6                <1> 	jmp	short namei_3
  3655                              <1> 		; br 2b
  3656                              <1> 
  3657                              <1> 	; 18/07/2013
  3658                              <1> nib: 
  3659 000041CC 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3660 000041CE F9                  <1> 	stc
  3661                              <1> nig:
  3662 000041CF C3                  <1> 	retn
  3663                              <1> 
  3664                              <1> namei_err:
  3665                              <1> 	; 16/06/2015
  3666 000041D0 C705[17670000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3666 000041D8 0000                <1>
  3667 000041DA E929F0FFFF          <1> 	jmp	error
  3668                              <1> 
  3669                              <1> namei_4: ; 3:
  3670                              <1> 	; 18/10/2015
  3671                              <1> 	; 12/10/2015
  3672                              <1> 	; 21/08/2015
  3673                              <1> 	; 18/07/2015
  3674 000041DF 8B2D[E0660000]      <1> 	mov	ebp, [u.namep]
  3675                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3676 000041E5 BF[FC660000]        <1> 	mov 	edi, u.dirbuf + 2
  3677                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3678                              <1> 	; 18/10/2015
  3679 000041EA 8B35[38670000]      <1> 	mov	esi, [nbase]	
  3680 000041F0 668B0D[3C670000]    <1> 	mov	cx, [ncount]
  3681                              <1> 	;
  3682 000041F7 6621C9              <1> 	and	cx, cx
  3683 000041FA 7505                <1> 	jnz	short namei_5	
  3684                              <1> 	;
  3685 000041FC E890000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3686                              <1> 		; esi = physical address (page start + offset)
  3687                              <1> 		; ecx = byte count in the page
  3688                              <1> namei_5: ; 3:
  3689 00004201 45                  <1> 	inc	ebp ; 18/07/2015
  3690 00004202 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3691                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3692 00004203 08C0                <1> 	or 	al, al
  3693 00004205 741C                <1> 	jz 	short namei_7
  3694                              <1> 		; beq 3f / if char is nul, then the last char in string
  3695                              <1> 			; / has been moved
  3696 00004207 3C2F                <1> 	cmp	al, '/'
  3697                              <1> 		; cmp r4,$'/ / is char a </>
  3698 00004209 7418                <1> 	je 	short namei_7
  3699                              <1> 		; beq 3f
  3700                              <1> 	; 03/02/2022
  3701 0000420B 49                  <1> 	dec	ecx	
  3702                              <1> 	; 12/10/2015
  3703                              <1> 	;dec	cx ; remain byte count in the page
  3704 0000420C 7505                <1> 	jnz	short namei_6
  3705 0000420E E87E000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3706                              <1> 		; esi = physical address (page start + offset)
  3707                              <1> 		; ecx = byte count in the page
  3708                              <1> namei_6:
  3709 00004213 81FF[04670000]      <1>         cmp     edi, u.dirbuf + 10
  3710                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3711                              <1> 				     ; / all 8 bytes of file name
  3712 00004219 74E6                <1> 	je	short namei_5
  3713                              <1> 		; beq 3b
  3714 0000421B AE                  <1> 	scasb	
  3715                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3716                              <1> 			      ; / char read from directory
  3717 0000421C 74E3                <1> 	je 	short namei_5
  3718                              <1> 		; beq 3b / branch if chars match
  3719                              <1> namei_9:
  3720 0000421E E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3721                              <1> 		; br 2b / file names do not match go to next directory entry
  3722                              <1> namei_7: ; 3:
  3723 00004223 81FF[04670000]      <1> 	cmp	edi, u.dirbuf + 10
  3724                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3725 00004229 7406                <1> 	je	short namei_8
  3726                              <1> 		; beq 3f
  3727 0000422B 8A27                <1> 	mov 	ah, [edi]
  3728                              <1> 	;inc 	edi 
  3729 0000422D 20E4                <1> 	and 	ah, ah
  3730                              <1> 		; tstb (r3)+ /
  3731                              <1>         ;jnz	namei_3
  3732                              <1> 		; bne 2b
  3733                              <1> 	; 03/02/2020
  3734 0000422F 75ED                <1> 	jnz	short namei_9
  3735                              <1> namei_8: ; 3
  3736 00004231 892D[E0660000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3737                              <1> 		; mov r2,u.namep / u.namep points to char 
  3738                              <1> 			       ; / following a / or nul
  3739                              <1> 	;mov	bx, [u.dirbuf]
  3740                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3741                              <1> 				; / entry to r1
  3742                              <1> 	;;;;
  3743                              <1> 	; 14/05/2022 - Retro UNIX (8086/386) feature only !
  3744                              <1> 	; ! 'pwd' utility modification !
  3745                              <1> 	; ((if directory entry name is a dotdot)))
  3746                              <1> 	;; check if it is mounted device's root directory inode
  3747                              <1> 	; and if so, replace it with parent dir inode number
  3748                              <1> 	;  of mounting directory in [mntp].
  3749                              <1> 
  3750 00004237 668B1D[FA660000]    <1> 	mov	bx, [u.dirbuf]
  3751                              <1> 
  3752 0000423E 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3753 00004242 753C                <1> 	jne	short namei_11
  3754                              <1> 
  3755 00004244 663B1D[A8660000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3756 0000424B 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3757                              <1> 
  3758                              <1> 	;cmp	[idev], bh ; 0
  3759 0000424D 383D[AC660000]      <1> 	cmp	[cdev], bh ; 0
  3760                              <1> 			; 0 = root fs, dev num in [rdev]
  3761                              <1> 			; 1 = mounted, dev num in [mdev]
  3762 00004253 762B                <1> 	jna	short namei_11
  3763                              <1> 
  3764                              <1> 	; dotdot (parent directory link) check
  3765 00004255 66813D[FC660000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3765 0000425D 2E                  <1>
  3766 0000425E 7520                <1> 	jne	short namei_11
  3767 00004260 803D[FE660000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3768 00004267 7517                <1> 	jne	short namei_11
  3769                              <1> 	
  3770                              <1> 	; (This may not be necessary because [idev] = 1
  3771                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3772 00004269 66391D[B2660000]    <1> 	cmp	[mnti], bx ; 41
  3773 00004270 760E                <1> 	jna	short namei_11
  3774                              <1> 	
  3775                              <1> 	; change inumber to parent dir inum of mount directory
  3776 00004272 668B1D[B4660000]    <1> 	mov	bx, [mntp]
  3777 00004279 C605[AC660000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3778                              <1> namei_11:
  3779                              <1> 	;;;;
  3780                              <1> 
  3781 00004280 20C0                <1> 	and 	al, al
  3782                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3783                              <1> 		      ;  / if r4 = </> then go to next directory
  3784                              <1> 	; 15/05/2022
  3785 00004282 6689D8              <1> 	mov	ax, bx
  3786                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3787                              <1>   	; 03/02/2022
  3788 00004285 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3789                              <1> 	;jnz	namei_2 
  3790                              <1> 		; bne 1b
  3791                              <1> 	; AX = i-number of the file
  3792                              <1> ;;nig:
  3793 0000428A C3                  <1> 	retn
  3794                              <1> 		; tst (r0)+ / gives non-error return
  3795                              <1> ;;nib:
  3796                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3797                              <1> 		       ; ax = 0 -> file not found 
  3798                              <1> ;;	stc	; 27/05/2013
  3799                              <1> ;;	retn
  3800                              <1> 		; rts r0
  3801                              <1> 
  3802                              <1> trans_addr_nmbp:
  3803                              <1> 	; 03/02/2022
  3804                              <1> 	; 18/10/2015
  3805                              <1> 	; 12/10/2015
  3806 0000428B 8B2D[E0660000]      <1> 	mov 	ebp, [u.namep]
  3807                              <1> trans_addr_nm:
  3808                              <1> 	; 03/02/2022
  3809                              <1> 	; Convert virtual (pathname) address to physical address
  3810                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3811                              <1> 	; 18/10/2015
  3812                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3813                              <1> 	; 02/07/2015
  3814                              <1> 	; 17/06/2015
  3815                              <1> 	; 16/06/2015
  3816                              <1> 	;
  3817                              <1> 	; INPUTS: 
  3818                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3819                              <1> 	;	[u.pgdir] = user's page directory
  3820                              <1> 	; OUTPUT:
  3821                              <1> 	;       esi = physical address of the pathname
  3822                              <1> 	;	ecx = remain byte count in the page
  3823                              <1> 	;
  3824                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3825                              <1> 	;
  3826                              <1> 
  3827                              <1> 	; 03/02/2022
  3828 00004291 29C9                <1> 	sub	ecx, ecx
  3829                              <1> 
  3830 00004293 833D[1F670000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3831 0000429A 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3832                              <1> 				     ; it is already physical address
  3833 0000429C 50                  <1>    	push	eax	
  3834 0000429D 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3835 0000429F E849E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3836 000042A4 7204                <1> 	jc	short tr_addr_nm_err
  3837                              <1> 	; 18/10/2015
  3838                              <1> 	; eax = physical address 
  3839                              <1> 	; cx = remain byte count in page (1-4096) 
  3840                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3841 000042A6 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3842 000042A8 58                  <1> 	pop	eax 
  3843 000042A9 C3                  <1> 	retn
  3844                              <1> 
  3845                              <1> tr_addr_nm_err:
  3846 000042AA A3[17670000]        <1> 	mov	[u.error], eax
  3847                              <1> 	;pop 	eax
  3848 000042AF E954EFFFFF          <1> 	jmp	error
  3849                              <1> 
  3850                              <1> trans_addr_nmk:
  3851                              <1> 	; 12/10/2015
  3852                              <1> 	; 02/07/2015
  3853 000042B4 8B35[E0660000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3854                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3855                              <1> 	; 03/02/2022
  3856 000042BA B510                <1> 	mov	ch, PAGE_SIZE/256
  3857 000042BC C3                  <1> 	retn
  3858                              <1> 
  3859                              <1> syschdir:
  3860                              <1> 	; 03/02/2022
  3861                              <1> 	; / makes the directory specified in the argument
  3862                              <1> 	; / the current directory
  3863                              <1> 	;
  3864                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3865                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3866                              <1> 	;
  3867                              <1> 	; 'syschdir' makes the directory specified in its argument
  3868                              <1> 	; the current working directory.
  3869                              <1> 	;
  3870                              <1> 	; Calling sequence:
  3871                              <1> 	;	syschdir; name
  3872                              <1> 	; Arguments:
  3873                              <1> 	;	name - address of the path name of a directory
  3874                              <1> 	;	       terminated by nul byte.	
  3875                              <1> 	; Inputs: -
  3876                              <1> 	; Outputs: -
  3877                              <1> 	; ...............................................................
  3878                              <1> 	;				
  3879                              <1> 	; Retro UNIX 8086 v1 modification:
  3880                              <1> 	;	 The user/application program puts address of 
  3881                              <1> 	;	 the path name in BX register as 'syschdir' 
  3882                              <1> 	; 	 system call argument.
  3883                              <1> 
  3884 000042BD 891D[E0660000]      <1> 	mov	[u.namep], ebx
  3885                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3886 000042C3 E841FEFFFF          <1> 	call	namei
  3887                              <1> 		; jsr r0,namei / find its i-number
  3888                              <1> 	;jc	error
  3889                              <1> 		; br error3
  3890 000042C8 730F                <1> 	jnc	short syschdir0
  3891                              <1> 	; 'directory not found !' error
  3892 000042CA C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3892 000042D2 0000                <1>
  3893 000042D4 E92FEFFFFF          <1> 	jmp	error
  3894                              <1> syschdir0:
  3895                              <1> 	; 03/02/2022
  3896 000042D9 B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3897 000042DB E812070000          <1> 	call	access
  3898                              <1> 		; jsr r0,access; 2 / get i-node into core
  3899                              <1> 	; 03/02/2022
  3900 000042E0 F605[C5630000]40    <1> 	test	byte [i.flgs+1], 40h
  3901                              <1> 	;test	word [i.flgs], 4000h
  3902                              <1> 		; bit $40000,i.flgs / is it a directory?
  3903                              <1> 	;jz	error 
  3904                              <1> 		; beq error3 / no error
  3905 000042E7 750F                <1> 	jnz	short syschdir1
  3906 000042E9 C705[17670000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3906 000042F1 0000                <1>
  3907 000042F3 E910EFFFFF          <1> 	jmp	error
  3908                              <1> syschdir1:
  3909 000042F8 66A3[CC660000]      <1> 	mov	[u.cdir], ax
  3910                              <1> 		; mov r1,u.cdir / move i-number to users 
  3911                              <1> 			      ; / current directory
  3912 000042FE 66A1[AC660000]      <1> 	mov	ax, [cdev]
  3913 00004304 66A3[0C670000]      <1> 	mov	[u.cdrv], ax
  3914                              <1> 		; mov cdev,u.cdev / move its device to users 
  3915                              <1> 			        ; / current device
  3916 0000430A E919EFFFFF          <1> 	jmp	sysret
  3917                              <1> 		; br sysret3
  3918                              <1> 	
  3919                              <1> syschmod: ; < change mode of file >
  3920                              <1> 	; 29/04/2022 (bugfix)
  3921                              <1> 	; 03/02/2022
  3922                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3923                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3924                              <1> 	;
  3925                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3926                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3927                              <1> 	; changed to 'mode'.
  3928                              <1> 	;
  3929                              <1> 	; Calling sequence:
  3930                              <1> 	;	syschmod; name; mode
  3931                              <1> 	; Arguments:
  3932                              <1> 	;	name - address of the file name
  3933                              <1> 	;	       terminated by null byte.
  3934                              <1> 	;	mode - (new) mode/flags < attributes >
  3935                              <1> 	;	
  3936                              <1> 	; Inputs: -
  3937                              <1> 	; Outputs: -
  3938                              <1> 	; ...............................................................
  3939                              <1> 	;				
  3940                              <1> 	; Retro UNIX 8086 v1 modification: 
  3941                              <1> 	;       'syschmod' system call has two arguments; so,
  3942                              <1> 	;	* 1st argument, name is pointed to by BX register
  3943                              <1> 	;	* 2nd argument, mode is in CX register
  3944                              <1> 	;
  3945                              <1> 	; Mode bits (Flags):
  3946                              <1> 	;	bit 0 - write permission for non-owner (1)
  3947                              <1> 	;	bit 1 - read permission for non-owner (2)
  3948                              <1> 	;	bit 2 - write permission for owner (4)
  3949                              <1> 	;	bit 3 - read permission for owner (8)
  3950                              <1> 	;	bit 4 - executable flag (16) 	
  3951                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3952                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3953                              <1> 	;	bit 12 - large file flag (4096)
  3954                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3955                              <1> 	;	bit 14 - directory flag (16384)
  3956                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3957                              <1> 
  3958                              <1> 	; / name; mode
  3959 0000430F E815000000          <1> 	call	isown
  3960                              <1> 		;jsr r0,isown / get the i-node and check user status
  3961                              <1> 	; 03/02/2022
  3962 00004314 F605[C5630000]40    <1> 	test	byte [i.flgs+1], 40h
  3963                              <1> 	;test	word [i.flgs], 4000h
  3964                              <1> 		; bit $40000,i.flgs / directory?
  3965 0000431B 7402                <1> 	jz	short syschmod1
  3966                              <1> 		; beq 2f / no
  3967                              <1> 	; AL = (new) mode
  3968 0000431D 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3969                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3970                              <1> 			   ; / executable modes
  3971                              <1> syschmod1: ; 2:
  3972 0000431F A2[C4630000]        <1> 	mov	[i.flgs], al	
  3973                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3974                              <1> 	;jmp	short isown1
  3975                              <1> 	;	; br 1f ; (jmp sysret4)
  3976                              <1> 	; 29/04/2022
  3977 00004324 E9FFEEFFFF          <1> 	jmp	sysret
  3978                              <1> 
  3979                              <1> isown:
  3980                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3981                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3982                              <1> 	;
  3983                              <1> 	; 'isown' is given a file name (the 1st argument).
  3984                              <1> 	;  It find the i-number of that file via 'namei' 
  3985                              <1> 	;  then gets the i-node into core via 'iget'.
  3986                              <1> 	;  It then tests to see if the user is super user. 
  3987                              <1> 	;  If not, it cheks to see if the user is owner of 
  3988                              <1> 	;  the file. If he is not an error occurs.
  3989                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3990                              <1> 	;  the inode has been modificed and the 2nd argument of
  3991                              <1> 	;  the call is put in r2.
  3992                              <1> 	;
  3993                              <1> 	; INPUTS ->
  3994                              <1> 	;    arguments of syschmod and syschown calls
  3995                              <1> 	; OUTPUTS ->
  3996                              <1> 	;    u.uid - id of user
  3997                              <1> 	;    imod - set to a 1
  3998                              <1> 	;    r2 - contains second argument of the system call				 	
  3999                              <1> 	;
  4000                              <1> 	;   ((AX=R2) output as 2nd argument)
  4001                              <1> 	;
  4002                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4003                              <1> 	;
  4004                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4005                              <1> 	;; ! 2nd argument on top of stack !
  4006                              <1> 	;; 22/06/2015 - 32 bit modifications
  4007                              <1> 	;; 07/07/2013
  4008 00004329 891D[E0660000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4009 0000432F 51                  <1> 	push 	ecx ;; 2nd argument
  4010                              <1> 	;;
  4011 00004330 E8D4FDFFFF          <1> 	call	namei
  4012                              <1> 		; jsr r0,namei / get its i-number
  4013                              <1>        ; Retro UNIX 8086 v1 modification !
  4014                              <1>        ; ax = 0 -> file not found 
  4015                              <1> 	;and	ax, ax
  4016                              <1> 	;jz	error
  4017                              <1> 	;jc	error ; 27/05/2013
  4018                              <1> 		; br error3
  4019 00004335 730F                <1> 	jnc	short isown0
  4020                              <1> 	; 'file not found !' error
  4021 00004337 C705[17670000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4021 0000433F 0000                <1>
  4022 00004341 E9C2EEFFFF          <1> 	jmp	error
  4023                              <1> isown0:
  4024 00004346 E8D3050000          <1> 	call	iget
  4025                              <1> 		; jsr r0,iget / get i-node into core
  4026 0000434B A0[0E670000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4027 00004350 08C0                <1> 	or	al, al
  4028                              <1> 		; tstb u.uid / super user?
  4029 00004352 7417                <1> 	jz	short isown1
  4030                              <1> 		; beq 1f / yes, branch
  4031 00004354 3A05[C7630000]      <1> 	cmp	al, [i.uid]
  4032                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4033                              <1> 				 ; / the file
  4034                              <1> 	;jne	error
  4035                              <1> 		; beq 1f / yes
  4036                              <1> 		; jmp error3 / no, error
  4037 0000435A 740F                <1> 	je	short isown1
  4038                              <1> 
  4039 0000435C C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4039 00004364 0000                <1>
  4040                              <1> 			;  'permission denied !' error
  4041 00004366 E99DEEFFFF          <1> 	jmp	error
  4042                              <1> isown1: ; 1:
  4043 0000436B E8B8060000          <1> 	call	setimod
  4044                              <1> 		; jsr r0,setimod / indicates 
  4045                              <1> 		;	       ; / i-node has been modified
  4046 00004370 58                  <1> 	pop	eax ; 2nd argument
  4047                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4048                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4049 00004371 C3                  <1> 	retn
  4050                              <1> 		; rts r0
  4051                              <1> 
  4052                              <1> ;;arg:  ; < get system call arguments >
  4053                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4054                              <1> 	; of form:
  4055                              <1> 	;	sys 'routine' ; arg1
  4056                              <1> 	;		or
  4057                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4058                              <1> 	;		or
  4059                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4060                              <1> 	;	
  4061                              <1> 	; INPUTS ->
  4062                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4063                              <1> 	;	This pointers's value is actually the value of
  4064                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4065                              <1> 	;	made to process the sys instruction
  4066                              <1> 	;    r0 - contains the return address for the routine
  4067                              <1> 	;	that called arg. The data in the word pointer 
  4068                              <1> 	;	to by the return address is used as address
  4069                              <1> 	;	in which the extracted argument is stored   		
  4070                              <1> 	;    	
  4071                              <1> 	; OUTPUTS ->
  4072                              <1> 	;    'address' - contains the extracted argument 
  4073                              <1> 	;    u.sp+18 - is incremented by 2 
  4074                              <1> 	;    r1 - contains the extracted argument
  4075                              <1> 	;    r0 - points to the next instruction to be
  4076                              <1> 	;	 executed in the calling routine.
  4077                              <1> 	;
  4078                              <1>   
  4079                              <1> 	; mov u.sp,r1
  4080                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4081                              <1> 			; / into argument of arg2
  4082                              <1> 	; add $2,18.(r1) / point pc on stack 
  4083                              <1> 			      ; / to next system argument
  4084                              <1> 	; rts r0
  4085                              <1> 
  4086                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4087                              <1> 	; 'arg2' takes first argument in system call
  4088                              <1> 	;  (pointer to name of the file) and puts it in location
  4089                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4090                              <1> 	;  and on top of the stack
  4091                              <1> 	;	
  4092                              <1> 	; INPUTS ->
  4093                              <1> 	;    u.sp, r0
  4094                              <1> 	;    	
  4095                              <1> 	; OUTPUTS ->
  4096                              <1> 	;    u.namep
  4097                              <1> 	;    u.off 
  4098                              <1> 	;    u.off pushed on stack
  4099                              <1> 	;    r1
  4100                              <1> 	;
  4101                              <1> 
  4102                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4103                              <1> 				; / first arg in sys call
  4104                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4105                              <1> 				; / second arg in sys call
  4106                              <1> 	; mov r0,r1 / r0 points to calling routine
  4107                              <1> 	; mov (sp),r0 / put operation code back in r0
  4108                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4109                              <1> 			; / on stack
  4110                              <1> 	; jmp (r1) / return to calling routine
  4111                              <1> 
  4112                              <1> syschown: ; < change owner of file >
  4113                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4114                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4115                              <1> 	;
  4116                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4117                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4118                              <1> 	; changed to 'owner'
  4119                              <1> 	;
  4120                              <1> 	; Calling sequence:
  4121                              <1> 	;	syschown; name; owner
  4122                              <1> 	; Arguments:
  4123                              <1> 	;	name - address of the file name
  4124                              <1> 	;	       terminated by null byte.
  4125                              <1> 	;	owner - (new) owner (number/ID)
  4126                              <1> 	;	
  4127                              <1> 	; Inputs: -
  4128                              <1> 	; Outputs: -
  4129                              <1> 	; ...............................................................
  4130                              <1> 	;				
  4131                              <1> 	; Retro UNIX 8086 v1 modification: 
  4132                              <1> 	;       'syschown' system call has two arguments; so,
  4133                              <1> 	;	* 1st argument, name is pointed to by BX register
  4134                              <1> 	;	* 2nd argument, owner number is in CX register
  4135                              <1> 	;
  4136                              <1> 	; / name; owner
  4137 00004372 E8B2FFFFFF          <1> 	call	isown
  4138                              <1> 		; jsr r0,isown / get the i-node and check user status
  4139 00004377 803D[0E670000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4140                              <1> 		; tstb u.uid / super user
  4141 0000437E 7418                <1> 	jz	short syschown1
  4142                              <1> 		; beq 2f / yes, 2f
  4143 00004380 F605[C4630000]20    <1>         test    byte [i.flgs], 20h ; 32
  4144                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4145                              <1> 	;jnz	error
  4146                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4147 00004387 740F                <1> 	jz	short syschown1
  4148                              <1> 	; 'permission denied !'
  4149 00004389 C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4149 00004391 0000                <1>
  4150 00004393 E970EEFFFF          <1> 	jmp	error
  4151                              <1> syschown1: ; 2:
  4152                              <1> 	; AL = owner (number/ID)
  4153 00004398 A2[C7630000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4154                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4155                              <1> 			       ; / in the i-node
  4156 0000439D E986EEFFFF          <1> 	jmp	sysret
  4157                              <1> 	; 1: 
  4158                              <1> 		; jmp sysret4
  4159                              <1> 	; 3:
  4160                              <1> 		; jmp	error
  4161                              <1> 
  4162                              <1> systime: ; / get time of year
  4163                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4164                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4165                              <1> 	;
  4166                              <1> 	; 20/06/2013
  4167                              <1> 	; 'systime' gets the time of the year.
  4168                              <1> 	; The present time is put on the stack.
  4169                              <1> 	;
  4170                              <1> 	; Calling sequence:
  4171                              <1> 	;	systime
  4172                              <1> 	; Arguments: -
  4173                              <1> 	;	
  4174                              <1> 	; Inputs: -
  4175                              <1> 	; Outputs: sp+2, sp+4 - present time
  4176                              <1> 	; ...............................................................
  4177                              <1> 	;	
  4178                              <1> 	; Retro UNIX 8086 v1 modification: 
  4179                              <1> 	;       'systime' system call will return to the user
  4180                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4181                              <1> 	;
  4182                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4183                              <1> 	;	system call for PC compatibility !!		 	
  4184                              <1> 
  4185 000043A2 E8AFE9FFFF          <1> 	call 	epoch
  4186 000043A7 A3[C8660000]        <1> 	mov 	[u.r0], eax
  4187                              <1> 		; mov s.time,4(sp)
  4188                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4189                              <1> 				   ; / on the stack
  4190                              <1> 		; br sysret4
  4191 000043AC E977EEFFFF          <1> 	jmp	sysret 
  4192                              <1> 
  4193                              <1> sysstime: ; / set time
  4194                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4195                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4196                              <1> 	;
  4197                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4198                              <1> 	;
  4199                              <1> 	; Calling sequence:
  4200                              <1> 	;	sysstime
  4201                              <1> 	; Arguments: -
  4202                              <1> 	;	
  4203                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4204                              <1> 	; Outputs: -
  4205                              <1> 	; ...............................................................
  4206                              <1> 	;	
  4207                              <1> 	; Retro UNIX 8086 v1 modification: 
  4208                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4209                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4210                              <1> 	; 
  4211                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4212                              <1> 	;	to get sysstime system call arguments from the user;
  4213                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4214                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4215                              <1> 	;
  4216                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4217                              <1> 	;	system call for PC compatibility !!	
  4218                              <1> 
  4219 000043B1 803D[0E670000]00    <1> 	cmp	byte [u.uid], 0
  4220                              <1> 		; tstb u.uid / is user the super user
  4221                              <1> 	;ja	error
  4222                              <1> 		; bne error4 / no, error
  4223 000043B8 760F                <1> 	jna	short systime1
  4224                              <1> 	; 'permission denied !'
  4225 000043BA C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4225 000043C2 0000                <1>
  4226 000043C4 E93FEEFFFF          <1> 	jmp	error
  4227                              <1> systime1:
  4228                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4229                              <1> 	; EBX = unix (epoch) time (from user)
  4230 000043C9 89D8                <1> 	mov	eax, ebx
  4231 000043CB E806EBFFFF          <1> 	call 	set_date_time
  4232                              <1> 		; mov 4(sp),s.time
  4233                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4234 000043D0 E953EEFFFF          <1> 	jmp	sysret
  4235                              <1> 		; br sysret4
  4236                              <1> 
  4237                              <1> sysbreak:
  4238                              <1> 	; 18/10/2015
  4239                              <1> 	; 07/10/2015
  4240                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4241                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4242                              <1> 	;
  4243                              <1> 	; 'sysbreak' sets the programs break points. 
  4244                              <1> 	; It checks the current break point (u.break) to see if it is
  4245                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4246                              <1> 	; even address (if it was odd) and the area between u.break
  4247                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4248                              <1> 	; in u.break and control is passed to 'sysret'.
  4249                              <1> 	;
  4250                              <1> 	; Calling sequence:
  4251                              <1> 	;	sysbreak; addr
  4252                              <1> 	; Arguments: -
  4253                              <1> 	;	
  4254                              <1> 	; Inputs: u.break - current breakpoint
  4255                              <1> 	; Outputs: u.break - new breakpoint 
  4256                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4257                              <1> 	; ...............................................................
  4258                              <1> 	;	
  4259                              <1> 	; Retro UNIX 8086 v1 modification:
  4260                              <1> 	;	The user/application program puts breakpoint address
  4261                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4262                              <1> 	; 	(argument transfer method 1)
  4263                              <1> 	;
  4264                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4265                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4266                              <1> 	;  NOTE:
  4267                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4268                              <1> 	;	'u.break' address) of user's memory for original unix's
  4269                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4270                              <1> 
  4271                              <1> 		; mov u.break,r1 / move users break point to r1
  4272                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4273                              <1> 		; blos 1f / yes, 1f
  4274                              <1> 	; 23/06/2015
  4275 000043D5 8B2D[F4660000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4276                              <1> 	;and	ebp, ebp
  4277                              <1> 	;jz	short sysbreak_3 
  4278                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4279                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4280 000043DB 8B15[C0660000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4281 000043E1 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4282                              <1> 	; 07/10/2015
  4283 000043E4 891D[F4660000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4284                              <1> 	;
  4285 000043EA 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4286                              <1> 			   ; with top of user's stack (virtual!)
  4287 000043EC 7327                <1> 	jnb	short sysbreak_3
  4288                              <1> 		; cmp r1,sp / is it the same or higher 
  4289                              <1> 			  ; / than the stack?
  4290                              <1> 		; bhis 1f / yes, 1f
  4291 000043EE 89DE                <1> 	mov	esi, ebx
  4292 000043F0 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4293 000043F2 7621                <1> 	jna	short sysbreak_3 
  4294                              <1> 	;push	ebx
  4295                              <1> sysbreak_1:
  4296 000043F4 89EB                <1> 	mov	ebx, ebp  
  4297 000043F6 E8F2E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4298 000043FB 0F82A9FEFFFF        <1> 	jc	tr_addr_nm_err
  4299                              <1> 	; 18/10/2015
  4300 00004401 89C7                <1> 	mov	edi, eax 
  4301 00004403 29C0                <1> 	sub	eax, eax ; 0
  4302                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4303 00004405 39CE                <1> 	cmp	esi, ecx
  4304 00004407 7302                <1> 	jnb	short sysbreak_2
  4305 00004409 89F1                <1> 	mov	ecx, esi
  4306                              <1> sysbreak_2:
  4307 0000440B 29CE                <1> 	sub	esi, ecx
  4308 0000440D 01CD                <1> 	add	ebp, ecx
  4309 0000440F F3AA                <1> 	rep 	stosb
  4310 00004411 09F6                <1> 	or	esi, esi
  4311 00004413 75DF                <1> 	jnz	short sysbreak_1
  4312                              <1> 	;
  4313                              <1> 		; bit $1,r1 / is it an odd address
  4314                              <1> 		; beq 2f / no, its even
  4315                              <1> 		; clrb (r1)+ / yes, make it even
  4316                              <1> 	; 2: / clear area between the break point and the stack
  4317                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4318                              <1> 		; bhis 1f / yes, quit
  4319                              <1> 		; clr (r1)+ / clear word
  4320                              <1> 		; br 2b / go back
  4321                              <1> 	;pop	ebx
  4322                              <1> sysbreak_3: ; 1:
  4323                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4324                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4325                              <1> 			; / in u.break (set new break point)
  4326                              <1> 		; br sysret4 / br sysret
  4327 00004415 E90EEEFFFF          <1> 	jmp	sysret
  4328                              <1> 
  4329                              <1> maknod: 
  4330                              <1> 	; 12/02/2022
  4331                              <1> 	; 03/02/2022
  4332                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4333                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4334                              <1> 	;
  4335                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4336                              <1> 	; for this i-node in the current directory.
  4337                              <1> 	;
  4338                              <1> 	; INPUTS ->
  4339                              <1> 	;    r1 - contains mode
  4340                              <1> 	;    ii - current directory's i-number	
  4341                              <1> 	;    	
  4342                              <1> 	; OUTPUTS ->
  4343                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4344                              <1> 	;    i.flgs - flags in new i-node 
  4345                              <1> 	;    i.uid - filled with u.uid
  4346                              <1> 	;    i.nlks - 1 is put in the number of links
  4347                              <1> 	;    i.ctim - creation time				
  4348                              <1> 	;    i.ctim+2 - modification time
  4349                              <1> 	;    imod - set via call to setimod
  4350                              <1> 	;	
  4351                              <1> 	; ((AX = R1)) input
  4352                              <1> 	;
  4353                              <1> 	; (Retro UNIX Prototype : 
  4354                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4355                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4356                              <1> 
  4357                              <1> 	; / r1 contains the mode
  4358 0000441A 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4359                              <1> 		; bis $100000,r1 / allocate flag set
  4360 0000441D 6650                <1> 	push	ax ; *
  4361                              <1> 		; mov r1,-(sp) / put mode on stack
  4362                              <1> 	; 31/07/2013
  4363 0000441F 66A1[A8660000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4364                              <1> 		; mov ii,r1 / move current i-number to r1
  4365 00004425 B201                <1> 	mov	dl, 1 ; owner flag mask
  4366 00004427 E8C6050000          <1> 	call	access	
  4367                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4368                              <1> 	; 03/02/2022
  4369 0000442C 50                  <1> 	push	eax ; **
  4370                              <1> 	;push	ax
  4371                              <1> 		; mov r1,-(sp) / put i-number on stack
  4372 0000442D 66B82800            <1> 	mov	ax, 40
  4373                              <1> 		; mov $40.,r1 / r1 = 40
  4374                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4375 00004431 6640                <1> 	inc	ax
  4376                              <1> 		; inc r1 / r1 = r1 + 1
  4377 00004433 E87F060000          <1> 	call	imap
  4378                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4379                              <1> 			    ; /	inode map in r2 & m
  4380                              <1>   
  4381                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4382                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4383                              <1> 
  4384                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4385                              <1> 	;	       Inode count must be checked here
  4386                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4387                              <1> 
  4388                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4389                              <1> 	; (inode count check)
  4390                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4391                              <1> 
  4392 00004438 730F                <1> 	jnc	short maknod2
  4393                              <1> 
  4394                              <1> 	; no free inode in inode table !
  4395 0000443A C705[17670000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4395 00004442 0000                <1>
  4396                              <1> 			; miscellaneous/other errors
  4397 00004444 E9BFEDFFFF          <1> 	jmp	error	
  4398                              <1> maknod2: 	
  4399 00004449 8413                <1> 	test	[ebx], dl
  4400                              <1> 		; bitb mq,(r2) / is the i-node active
  4401 0000444B 75E4                <1> 	jnz	short maknod1
  4402                              <1> 		; bne 1b / yes, try the next one
  4403 0000444D 0813                <1> 	or	[ebx], dl
  4404                              <1> 		; bisb mq,(r2) / no, make it active 
  4405                              <1> 			     ; / (put a 1 in the bit map)
  4406 0000444F E8CA040000          <1> 	call	iget
  4407                              <1> 		; jsr r0,iget / get i-node into core
  4408                              <1> 	; 03/02/2022
  4409 00004454 F605[C5630000]80    <1> 	test	byte [i.flgs+1], 80h
  4410                              <1> 	;test	word [i.flgs], 8000h 
  4411                              <1> 		; tst i.flgs / is i-node already allocated
  4412 0000445B 75D4                <1> 	jnz	short maknod1	
  4413                              <1> 		; blt 1b / yes, look for another one
  4414 0000445D 66A3[FA660000]      <1> 	mov	[u.dirbuf], ax
  4415                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4416                              <1> 	; 03/02/2022
  4417 00004463 58                  <1> 	pop	eax ; **
  4418                              <1> 	;pop	ax
  4419                              <1> 		; mov (sp)+,r1 / get current i-number back
  4420 00004464 E8B5040000          <1> 	call	iget
  4421                              <1> 		; jsr r0,iget / get i-node in core
  4422 00004469 E852F7FFFF          <1> 	call	mkdir
  4423                              <1> 		; jsr r0,mkdir / make a directory entry 
  4424                              <1> 			     ; / in current directory
  4425 0000446E 66A1[FA660000]      <1> 	mov	ax, [u.dirbuf]
  4426                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4427 00004474 E8A5040000          <1> 	call	iget
  4428                              <1> 		; jsr r0,iget / get it into core
  4429                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4430                              <1> 	;mov	ecx, 8
  4431                              <1> 	; 03/02/2022 
  4432 00004479 29C9                <1> 	sub	ecx, ecx
  4433 0000447B B108                <1> 	mov	cl, 8
  4434 0000447D 31C0                <1> 	xor	eax, eax ; 0
  4435 0000447F BF[C4630000]        <1> 	mov	edi, inode 
  4436 00004484 F3AB                <1> 	rep	stosd
  4437                              <1> 	;
  4438 00004486 668F05[C4630000]    <1> 	pop	word [i.flgs] ; *
  4439                              <1> 		; mov (sp)+,i.flgs / fill flags
  4440 0000448D 8A0D[0E670000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4441 00004493 880D[C7630000]      <1> 	mov 	[i.uid], cl
  4442                              <1> 		; movb u.uid,i.uid / user id	
  4443 00004499 C605[C6630000]01    <1> 	mov     byte [i.nlks], 1
  4444                              <1> 		; movb $1,i.nlks / 1 link
  4445                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4446                              <1> 	;mov	eax, [s.time]
  4447                              <1> 	;mov 	[i.ctim], eax
  4448                              <1> 	 	; mov s.time,i.ctim / time created
  4449                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4450                              <1> 	; Retro UNIX 8086 v1 modification !
  4451                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4452                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4453                              <1> 	;call setimod
  4454                              <1> 		; jsr r0,setimod / set modified flag
  4455                              <1> 	;retn
  4456                              <1> 		; rts r0 / return
  4457                              <1> 	; 03/02/2022
  4458 000044A0 E983050000          <1> 	jmp	setimod
  4459                              <1> 
  4460                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4461                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4462                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4463                              <1> 	;
  4464                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4465                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4466                              <1> 	; The file descriptor refers to a file open for reading or
  4467                              <1> 	; writing. The read (or write) pointer is set as follows:
  4468                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4469                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4470                              <1> 	;	  current location plus offset.
  4471                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4472                              <1> 	;	  size of file plus offset.
  4473                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4474                              <1> 	;
  4475                              <1> 	; Calling sequence:
  4476                              <1> 	;	sysseek; offset; ptrname
  4477                              <1> 	; Arguments:
  4478                              <1> 	;	offset - number of bytes desired to move 
  4479                              <1> 	;		 the r/w pointer
  4480                              <1> 	;	ptrname - a switch indicated above
  4481                              <1> 	;
  4482                              <1> 	; Inputs: r0 - file descriptor 
  4483                              <1> 	; Outputs: -
  4484                              <1> 	; ...............................................................
  4485                              <1> 	;	
  4486                              <1> 	; Retro UNIX 8086 v1 modification: 
  4487                              <1> 	;       'sysseek' system call has three arguments; so,
  4488                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4489                              <1> 	;	* 2nd argument, offset is in CX register
  4490                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4491                              <1> 	;	
  4492                              <1> 
  4493 000044A5 E822000000          <1> 	call	seektell
  4494                              <1> 	; AX = u.count
  4495                              <1> 	; BX = *u.fofp
  4496                              <1> 		; jsr r0,seektell / get proper value in u.count
  4497                              <1> 		; add u.base,u.count / add u.base to it
  4498 000044AA 0305[E8660000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4499 000044B0 8903                <1> 	mov	[ebx], eax
  4500                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4501 000044B2 E971EDFFFF          <1> 	jmp	sysret
  4502                              <1> 		; br sysret4
  4503                              <1> 
  4504                              <1> systell: ; / get the r/w pointer
  4505                              <1> 	; 03/02/2022
  4506                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4507                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4508                              <1> 	;
  4509                              <1> 	; Retro UNIX 8086 v1 modification:
  4510                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4511                              <1> 	; 	    it returns with error !
  4512                              <1> 	; Inputs: r0 - file descriptor 
  4513                              <1> 	; Outputs: r0 - file r/w pointer
  4514                              <1> 
  4515                              <1> 	;xor	ecx, ecx ; 0
  4516                              <1> 	;mov	edx, 1 ; 05/08/2013
  4517                              <1> 	; 03/02/2022
  4518 000044B7 29D2                <1> 	sub	edx, edx
  4519 000044B9 FEC2                <1> 	inc	dl
  4520                              <1> 	; edx = 1
  4521                              <1> 	;call 	seektell
  4522 000044BB E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4523                              <1> 	;mov	ebx, [u.fofp]
  4524 000044C0 8B03                <1> 	mov	eax, [ebx]
  4525 000044C2 A3[C8660000]        <1> 	mov	[u.r0], eax
  4526 000044C7 E95CEDFFFF          <1> 	jmp	sysret
  4527                              <1> 
  4528                              <1> ; Original unix v1 'systell' system call:
  4529                              <1> 		; jsr r0,seektell
  4530                              <1> 		; br error4
  4531                              <1> 
  4532                              <1> seektell:
  4533                              <1> 	; 03/02/2022
  4534                              <1> 	; 03/01/2016
  4535                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4536                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4537                              <1> 	;
  4538                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4539                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4540                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4541                              <1> 	; getf. The i-node is brought into core and then u.count
  4542                              <1> 	; is checked to see it is a 0, 1, or 2.
  4543                              <1> 	; If it is 0 - u.count stays the same
  4544                              <1> 	;          1 - u.count = offset (u.fofp)
  4545                              <1> 	;	   2 - u.count = i.size (size of file)
  4546                              <1> 	; 	 		
  4547                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4548                              <1> 	;	Argument 1, file descriptor is in BX;
  4549                              <1> 	;	Argument 2, offset is in CX;
  4550                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4551                              <1> 	;
  4552                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4553                              <1> 	; call 	arg
  4554                              <1> 	;
  4555                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4556                              <1> 	;
  4557 000044CC 890D[E8660000]      <1> 	mov 	[u.base], ecx ; offset
  4558                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4559                              <1> seektell0:
  4560 000044D2 8915[EC660000]      <1> 	mov 	[u.count], edx
  4561                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4562                              <1> 	; mov	ax, bx
  4563                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4564                              <1> 			     ; / (index in u.fp list)
  4565                              <1> 	; call	getf
  4566                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4567                              <1> 	; BX = file descriptor (file number)
  4568 000044D8 E8F9FBFFFF          <1> 	call	getf1
  4569                              <1> 	; 03/02/2022
  4570 000044DD 09C0                <1> 	or	eax, eax
  4571                              <1> 	;or	ax, ax ; i-number of the file
  4572                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4573                              <1> 		             ; / put it on the stack
  4574                              <1> 	;jz	error
  4575                              <1> 		; beq error4 / if i-number is 0, not active so error
  4576 000044DF 750F                <1> 	jnz	short seektell1
  4577 000044E1 C705[17670000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4577 000044E9 0000                <1>
  4578 000044EB E918EDFFFF          <1> 	jmp	error
  4579                              <1> seektell1:
  4580                              <1> 	;push	eax
  4581 000044F0 80FC80              <1> 	cmp	ah, 80h
  4582 000044F3 7203                <1> 	jb	short seektell2
  4583                              <1> 		; bgt .+4 / if its positive jump
  4584 000044F5 66F7D8              <1> 	neg	ax
  4585                              <1> 		; neg r1 / if not make it positive
  4586                              <1> seektell2:
  4587 000044F8 E821040000          <1> 	call	iget
  4588                              <1> 		; jsr r0,iget / get its i-node into core
  4589 000044FD 8B1D[D8660000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4590 00004503 803D[EC660000]01    <1> 	cmp	byte [u.count], 1
  4591                              <1> 		; cmp u.count,$1 / is ptr name =1
  4592 0000450A 7705                <1> 	ja	short seektell3
  4593                              <1> 		; blt 2f / no its zero
  4594 0000450C 740A                <1> 	je	short seektell_4
  4595                              <1> 		; beq 1f / yes its 1
  4596 0000450E 31C0                <1> 	xor	eax, eax
  4597                              <1> 	;jmp	short seektell_5
  4598 00004510 C3                  <1> 	retn
  4599                              <1> seektell3:
  4600                              <1> 	; 03/01/2016
  4601                              <1> 	;movzx  eax, word [i.size]
  4602 00004511 66A1[C8630000]      <1> 	mov	ax, [i.size]
  4603                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4604                              <1>                                    ; / in file in u.count
  4605                              <1> 	;jmp	short seektell_5
  4606                              <1> 		; br 2f
  4607 00004517 C3                  <1> 	retn
  4608                              <1> seektell_4: ; 1: / ptrname =1
  4609                              <1> 	;mov	ebx, [u.fofp]
  4610 00004518 8B03                <1> 	mov	eax, [ebx]
  4611                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4612                              <1> ;seektell_5: ; 2: / ptrname =0
  4613                              <1> 	;mov	[u.count], eax
  4614                              <1> 	;pop	eax 
  4615                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4616 0000451A C3                  <1> 	retn
  4617                              <1> 		; rts r0
  4618                              <1> 
  4619                              <1> sysintr: ; / set interrupt handling
  4620                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4621                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4622                              <1> 	;
  4623                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4624                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4625                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4626                              <1> 	; If one does the interrupt character in the tty buffer is
  4627                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4628                              <1> 	; 'sysret' is just called.	
  4629                              <1> 	;
  4630                              <1> 	; Calling sequence:
  4631                              <1> 	;	sysintr; arg
  4632                              <1> 	; Argument:
  4633                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4634                              <1> 	;	    - if 1, intterupts cause their normal result
  4635                              <1> 	;		 i.e force an exit.
  4636                              <1> 	;	    - if arg is a location within the program,
  4637                              <1> 	;		control is passed to that location when
  4638                              <1> 	;		an interrupt occurs.	
  4639                              <1> 	; Inputs: -
  4640                              <1> 	; Outputs: -
  4641                              <1> 	; ...............................................................
  4642                              <1> 	;	
  4643                              <1> 	; Retro UNIX 8086 v1 modification: 
  4644                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4645                              <1> 	;	then branches into sysquit.
  4646                              <1> 	;
  4647 0000451B 66891D[06670000]    <1> 	mov	[u.intr], bx
  4648                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4649                              <1> 		; br 1f / go into quit routine
  4650 00004522 E901EDFFFF          <1> 	jmp	sysret
  4651                              <1> 
  4652                              <1> sysquit:
  4653                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4654                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4655                              <1> 	;
  4656                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4657                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4658                              <1> 	; tty exists. If one does the interrupt character in the tty
  4659                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4660                              <1> 	; 'sysret' is just called.	
  4661                              <1> 	;
  4662                              <1> 	; Calling sequence:
  4663                              <1> 	;	sysquit; arg
  4664                              <1> 	; Argument:
  4665                              <1> 	;	arg - if 0, this call diables quit signals from the
  4666                              <1> 	;		typewriter (ASCII FS)
  4667                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4668                              <1> 	;		cease and a core image to be produced.
  4669                              <1> 	;		 i.e force an exit.
  4670                              <1> 	;	    - if arg is an addres in the program,
  4671                              <1> 	;		a quit causes control to sent to that
  4672                              <1> 	;		location.	
  4673                              <1> 	; Inputs: -
  4674                              <1> 	; Outputs: -
  4675                              <1> 	; ...............................................................
  4676                              <1> 	;	
  4677                              <1> 	; Retro UNIX 8086 v1 modification: 
  4678                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4679                              <1> 	;	then branches into 'sysret'.
  4680                              <1> 	;
  4681 00004527 66891D[08670000]    <1> 	mov	[u.quit], bx
  4682 0000452E E9F5ECFFFF          <1> 	jmp	sysret
  4683                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4684                              <1> 	;1:
  4685                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4686                              <1> 			      ; / to r1
  4687                              <1> 		; beq sysret4 / return to user
  4688                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4689                              <1> 			   ; / in the tty buffer
  4690                              <1> 		; br sysret4 / return to user
  4691                              <1> 
  4692                              <1> syssetuid: ; / set process id
  4693                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4694                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4695                              <1> 	;
  4696                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4697                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4698                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4699                              <1> 	; Only the super user can make this call.	
  4700                              <1> 	;
  4701                              <1> 	; Calling sequence:
  4702                              <1> 	;	syssetuid
  4703                              <1> 	; Arguments: -
  4704                              <1> 	;
  4705                              <1> 	; Inputs: (u.r0) - contains the process id.
  4706                              <1> 	; Outputs: -
  4707                              <1> 	; ...............................................................
  4708                              <1> 	;	
  4709                              <1> 	; Retro UNIX 8086 v1 modification: 
  4710                              <1> 	;       BL contains the (new) user ID of the current process
  4711                              <1> 
  4712                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4713 00004533 3A1D[0F670000]      <1> 	cmp	bl, [u.ruid] 
  4714                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4715                              <1> 			       ; / id number
  4716 00004539 741E                <1> 	je	short setuid1
  4717                              <1> 		; beq 1f / yes
  4718 0000453B 803D[0E670000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4719                              <1> 		; tstb u.uid / no, is current user the super user?
  4720                              <1> 	;ja	error
  4721                              <1> 		; bne error4 / no, error
  4722 00004542 760F                <1> 	jna	short setuid0
  4723 00004544 C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4723 0000454C 0000                <1>
  4724                              <1> 				; 'permission denied !' error
  4725 0000454E E9B5ECFFFF          <1> 	jmp	error
  4726                              <1> setuid0:
  4727 00004553 881D[0F670000]      <1> 	mov	[u.ruid], bl
  4728                              <1> setuid1: ; 1:
  4729 00004559 881D[0E670000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4730                              <1> 		; movb r1,u.uid / put process id in u.uid
  4731                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4732 0000455F E9C4ECFFFF          <1> 	jmp	sysret
  4733                              <1> 		; br sysret4 / system return
  4734                              <1> 
  4735                              <1> sysgetuid: ; < get user id >
  4736                              <1> 	; 03/02/2022
  4737                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4738                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4739                              <1> 	;
  4740                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4741                              <1> 	; The real user ID identifies the person who is logged in,
  4742                              <1> 	; in contradistinction to the effective user ID, which
  4743                              <1> 	; determines his access permission at each moment. It is thus
  4744                              <1> 	; useful to programs which operate using the 'set user ID'
  4745                              <1> 	; mode, to find out who invoked them.	
  4746                              <1> 	;
  4747                              <1> 	; Calling sequence:
  4748                              <1> 	;	syssetuid
  4749                              <1> 	; Arguments: -
  4750                              <1> 	;
  4751                              <1> 	; Inputs: -
  4752                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4753                              <1> 	; ...............................................................
  4754                              <1> 	;	
  4755                              <1> 	; Retro UNIX 8086 v1 modification: 
  4756                              <1> 	;       AL contains the real user ID at return.
  4757                              <1> 	;
  4758                              <1> 	;movzx 	eax, byte [u.ruid]
  4759                              <1> 	; 03/03/2022
  4760 00004564 A0[0F670000]        <1> 	mov	al, [u.ruid]
  4761 00004569 A3[C8660000]        <1> 	mov	[u.r0], eax
  4762                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4763 0000456E E9B5ECFFFF          <1> 	jmp	sysret
  4764                              <1> 		; br sysret4 / systerm return, sysret
  4765                              <1> 
  4766                              <1> anyi: 
  4767                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4768                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4769                              <1> 	;
  4770                              <1> 	; 'anyi' is called if a file deleted while open.
  4771                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4772                              <1> 	;
  4773                              <1> 	; INPUTS ->
  4774                              <1> 	;    r1 - contains an i-number
  4775                              <1> 	;    fsp - start of table containing open files
  4776                              <1> 	;
  4777                              <1> 	; OUTPUTS ->
  4778                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4779                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4780                              <1> 	;    if file not found - bit in i-node map is cleared
  4781                              <1> 	;    			 (i-node is freed)
  4782                              <1> 	;               all blocks related to i-node are freed
  4783                              <1> 	;	        all flags in i-node are cleared
  4784                              <1> 	; ((AX = R1)) input
  4785                              <1> 	;
  4786                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4787                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4788                              <1> 	;
  4789                              <1> 		; / r1 contains an i-number
  4790 00004573 BB[94640000]        <1> 	mov	ebx, fsp
  4791                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4792                              <1> anyi_1: ; 1:
  4793 00004578 663B03              <1> 	cmp	ax, [ebx]
  4794                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4795 0000457B 7433                <1> 	je	short anyi_3
  4796                              <1> 		; beq 1f / yes, 1f
  4797 0000457D 66F7D8              <1> 	neg	ax
  4798                              <1> 		; neg r1 / no complement r1
  4799 00004580 663B03              <1> 	cmp	ax, [ebx]
  4800                              <1> 		; cmp r1,(r2) / do they match now?
  4801 00004583 742B                <1> 	je	short anyi_3
  4802                              <1> 		; beq 1f / yes, transfer
  4803                              <1> 		; / i-numbers do not match
  4804 00004585 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4805                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4806                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4807 00004588 81FB[88660000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4808                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4809                              <1> 				; / are we at last entry in the table
  4810 0000458E 72E8                <1> 	jb	short anyi_1
  4811                              <1> 		; blt 1b / no, check next entries i-number
  4812                              <1> 	;cmp	ax, 32768
  4813 00004590 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4814                              <1> 		; tst r1 / yes, no match
  4815                              <1> 		; bge .+4
  4816 00004593 7203                <1> 	jb	short anyi_2
  4817 00004595 66F7D8              <1> 	neg	ax
  4818                              <1> 		; neg r1 / make i-number positive
  4819                              <1> anyi_2:	
  4820 00004598 E81A050000          <1> 	call	imap
  4821                              <1> 		; jsr r0,imap / get address of allocation bit 
  4822                              <1> 			    ; / in the i-map in r2
  4823                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4824                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4825                              <1>  	; not	dx
  4826 0000459D F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4827                              <1>         ;and	[ebx], dx
  4828 0000459F 2013                <1> 	and 	[ebx], dl 
  4829                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4830 000045A1 E8A4040000          <1> 	call	itrunc
  4831                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4832 000045A6 66C705[C4630000]00- <1>  	mov 	word [i.flgs], 0
  4832 000045AE 00                  <1>
  4833                              <1> 		; clr i.flgs / clear all flags in the i-node
  4834 000045AF C3                  <1> 	retn
  4835                              <1> 		;rts	r0 / return
  4836                              <1> anyi_3: ; 1: / i-numbers match
  4837 000045B0 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4838                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4839                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4840 000045B3 C3                  <1> 	retn
  4841                              <1> 		; rts r0
  2051                                  %include 'u3.s'        ; 10/05/2015
  2052                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2053                              <1> ; Last Modification: 03/02/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 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2064                              <1> ;
  2065                              <1> ; ****************************************************************************
  2066                              <1> ; 15/09/2015
  2067                              <1> 
  2068                              <1> tswitch: ; Retro UNIX 386 v1
  2069                              <1> tswap:
  2070                              <1> 	; 01/09/2015
  2071                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2072                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2073                              <1> 	; time out swap, called when a user times out.
  2074                              <1> 	; the user is put on the low priority queue.
  2075                              <1> 	; This is done by making a link from the last user
  2076                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2077                              <1> 	; then he is swapped out.
  2078                              <1> 	;
  2079                              <1> 	; Retro UNIX 386 v1 modification ->
  2080                              <1> 	;       swap (software task switch) is performed by changing
  2081                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2082                              <1> 	;	as in Retro UNIX 8086 v1.
  2083                              <1> 	;
  2084                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2085                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2086                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2087                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2088                              <1> 	;	compatibles was using 1MB segmented memory 
  2089                              <1> 	;	in 8086/8088 times.
  2090                              <1> 	;
  2091                              <1> 	; INPUTS ->
  2092                              <1> 	;    u.uno - users process number
  2093                              <1> 	;    runq+4 - lowest priority queue
  2094                              <1> 	; OUTPUTS ->
  2095                              <1> 	;    r0 - users process number
  2096                              <1> 	;    r2 - lowest priority queue address
  2097                              <1> 	;
  2098                              <1> 	; ((AX = R0, BX = R2)) output
  2099                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2100                              <1> 	;
  2101 000045B4 A0[11670000]        <1> 	mov 	al, [u.uno]
  2102                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2103                              <1> 		; mov  $runq+4,r2 
  2104                              <1> 			; / move lowest priority queue address to r2
  2105 000045B9 E8CD000000          <1>         call 	putlu
  2106                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2107                              <1> 		             ; / u.uno's user
  2108                              <1> 
  2109                              <1> switch: ; Retro UNIX 386 v1
  2110                              <1> swap:
  2111                              <1> 	; 03/02/2022
  2112                              <1> 	; 02/09/2015
  2113                              <1> 	; 01/09/2015
  2114                              <1> 	; 31/08/2015
  2115                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2116                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2117                              <1> 	; 'swap' is routine that controls the swapping of processes
  2118                              <1> 	; in and out of core.
  2119                              <1> 	;
  2120                              <1> 	; Retro UNIX 386 v1 modification ->
  2121                              <1> 	;       swap (software task switch) is performed by changing
  2122                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2123                              <1> 	;	as in Retro UNIX 8086 v1.
  2124                              <1> 	;
  2125                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2126                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2127                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2128                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2129                              <1> 	;	compatibles was using 1MB segmented memory 
  2130                              <1> 	;	in 8086/8088 times.
  2131                              <1> 	;
  2132                              <1> 	; INPUTS ->
  2133                              <1> 	;    runq table - contains processes to run.
  2134                              <1> 	;    p.link - contains next process in line to be run.
  2135                              <1> 	;    u.uno - process number of process in core	
  2136                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2137                              <1> 	; OUTPUTS ->
  2138                              <1> 	;    (original unix v1 -> present process to its disk block)
  2139                              <1> 	;    (original unix v1 -> new process into core -> 
  2140                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2141                              <1> 	;	   for new process)
  2142                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2143                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2144                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2145                              <1> 	;	 for now, it will swap the process if there is not
  2146                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2147                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2148                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2149                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2150                              <1> 	;
  2151                              <1> 	;    u.pri -points to highest priority run Q.
  2152                              <1> 	;    r2 - points to the run queue.
  2153                              <1> 	;    r1 - contains new process number
  2154                              <1> 	;    r0 - points to place in routine or process that called
  2155                              <1> 	;	  swap all user parameters
  2156                              <1> 	;				
  2157                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2158                              <1> 	;
  2159                              <1> swap_0:
  2160                              <1> 		;mov $300,*$ps / processor priority = 6
  2161 000045BE BE[BA660000]        <1> 	mov	esi, runq
  2162                              <1> 		; mov $runq,r2 / r2 points to runq table
  2163                              <1> swap_1: ; 1: / search runq table for highest priority process
  2164 000045C3 668B06              <1> 	mov	ax, [esi]
  2165 000045C6 6621C0              <1> 	and 	ax, ax
  2166                              <1>        		; tst (r2)+ / are there any processes to run 
  2167                              <1> 			  ; / in this Q entry
  2168 000045C9 7507                <1> 	jnz	short swap_2
  2169                              <1>        		; bne 1f / yes, process 1f
  2170                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2171                              <1> 			       ; / to end of table
  2172                              <1> 		; bne 1b / if not at end, go back
  2173 000045CB E8E0000000          <1> 	call	idle
  2174                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2175                              <1> 				       ; / all queues are empty
  2176 000045D0 EBF1                <1> 	jmp	short swap_1
  2177                              <1> 		; br swap
  2178                              <1> swap_2: ; 1:
  2179 000045D2 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2180                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2181                              <1>  		; mov r2,u.pri / set present user to this run queue
  2182                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2183 000045D5 38E0                <1> 	cmp	al, ah
  2184                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2185                              <1> 			      ; / in this Q to be run
  2186 000045D7 740A                <1> 	je	short swap_3
  2187                              <1>        		; beq 1f / yes
  2188                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2189                              <1> 	;movzx	ebx, al
  2190 000045D9 8AA3[33640000]      <1> 	mov	ah, [ebx+p.link-1] 
  2191 000045DF 8826                <1>        	mov	[esi], ah
  2192                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2193                              <1> 				       ; / in line into run queue
  2194 000045E1 EB05                <1> 	jmp	short swap_4
  2195                              <1>        		; br 2f
  2196                              <1> swap_3: ; 1:
  2197                              <1> 	;xor	dx, dx
  2198                              <1> 	; 03/02/2022
  2199 000045E3 31D2                <1> 	xor	edx, edx
  2200 000045E5 668916              <1> 	mov	[esi], dx
  2201                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2202                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2203                              <1>       ; / in new process if required
  2204                              <1>        		; clr *$ps / clear processor status
  2205 000045E8 8A25[11670000]      <1> 	mov 	ah, [u.uno]
  2206 000045EE 38C4                <1> 	cmp	ah, al
  2207                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2208                              <1> 			      ; / the process in core?
  2209 000045F0 743B                <1>        	je	short swap_8
  2210                              <1>        		; beq 2f / yes, don't have to swap
  2211                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2212                              <1> 			   ; / (address in routine that called swap)
  2213                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2214                              <1> 	; 01/09/2015
  2215                              <1> 	;mov	[u.usp], esp
  2216                              <1>        		; mov sp,u.usp / save stack pointer
  2217                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2218                              <1> 			       ; / to the stack pointer
  2219 000045F2 08E4                <1> 	or	ah, ah
  2220                              <1>        		; tstb u.uno / is the process # = 0
  2221 000045F4 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2222                              <1> 		; beq  1f / yes, kill process by overwriting
  2223                              <1> 	; 02/09/2015
  2224 000045F6 8925[C4660000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2225                              <1> 	;
  2226 000045FC E834000000          <1> 	call	wswap
  2227                              <1> 		;jsr r0,wswap / write out core to disk
  2228                              <1> 	 ; 31/08/2015
  2229                              <1> 	;movzx	ebx, al ; New (running) process number
  2230 00004601 EB1C                <1> 	jmp 	short swap_7
  2231                              <1> swap_6:
  2232                              <1> 	; 31/08/2015
  2233                              <1> 	; Deallocate memory pages belong to the process
  2234                              <1> 	; which is being terminated
  2235                              <1> 	; 14/05/2015 ('sysexit')
  2236                              <1>  	; Deallocate memory pages of the process
  2237                              <1> 	; (Retro UNIX 386 v1 modification !)
  2238                              <1> 	;
  2239                              <1> 	; movzx ebx, al
  2240 00004603 53                  <1> 	push	ebx
  2241 00004604 A1[1B670000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2242 00004609 8B1D[1F670000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2243 0000460F E81DE0FFFF          <1> 	call	deallocate_page_dir
  2244 00004614 A1[12670000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2245 00004619 E8ABE0FFFF          <1> 	call	deallocate_page
  2246 0000461E 5B                  <1> 	pop	ebx
  2247                              <1> swap_7: ;1: 
  2248                              <1> 	; 02/09/2015
  2249                              <1> 	; 31/08/2015
  2250                              <1> 	; 14/05/2015
  2251 0000461F C0E302              <1> 	shl	bl, 2 ; * 4 
  2252 00004622 8B83[50640000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2253                              <1> 	;cli
  2254 00004628 E831000000          <1> 	call	rswap
  2255                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2256                              <1> 		; jsr r0,rswap / read new process into core
  2257                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2258                              <1> 			      ; / to his program to its normal
  2259                              <1> 	; 01/09/2015
  2260                              <1> 	;mov	esp, [u.usp]	
  2261                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2262                              <1> 			     ; / new process stack
  2263                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2264                              <1> 			     ; / that just got swapped in, left off.,
  2265                              <1> 			     ; / i.e., transfer control to new process
  2266                              <1> 	;sti
  2267                              <1> swap_8: ;2:
  2268                              <1> 	; RETRO UNIX 8086 v1 modification !
  2269 0000462D C605[04670000]04    <1> 	mov	byte [u.quant], time_count 
  2270                              <1> 		; movb $30.,uquant / initialize process time quantum
  2271 00004634 C3                  <1> 	retn
  2272                              <1> 		; rts r0 / return
  2273                              <1> 
  2274                              <1> wswap:  ; < swap out, swap to disk >
  2275                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2276                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2277                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2278                              <1> 	; appropriate disk area.
  2279                              <1> 	;
  2280                              <1> 	; Retro UNIX 386 v1 modification ->
  2281                              <1> 	;       User (u) structure content and the user's register content
  2282                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2283                              <1> 	;	saving 'u' structure and user registers for task switching).
  2284                              <1> 	;	u.usp - points to kernel stack address which contains
  2285                              <1> 	;		user's registers while entering system call.  
  2286                              <1> 	;	u.sp  - points to kernel stack address 
  2287                              <1> 	;		to return from system call -for IRET-.
  2288                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2289                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2290                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2291                              <1> 	;
  2292                              <1> 	; Retro UNIX 8086 v1 modification ->
  2293                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2294                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2295                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2296                              <1> 	;	compatibles was using 1MB segmented memory 
  2297                              <1> 	;	in 8086/8088 times.
  2298                              <1> 	;
  2299                              <1> 	; INPUTS ->
  2300                              <1> 	;    u.break - points to end of program
  2301                              <1> 	;    u.usp - stack pointer at the moment of swap
  2302                              <1> 	;    core - beginning of process program		
  2303                              <1> 	;    ecore - end of core 	
  2304                              <1> 	;    user - start of user parameter area		
  2305                              <1> 	;    u.uno - user process number	
  2306                              <1> 	;    p.dska - holds block number of process	
  2307                              <1> 	; OUTPUTS ->
  2308                              <1> 	;    swp I/O queue
  2309                              <1> 	;    p.break - negative word count of process 
  2310                              <1> 	;    r1 - process disk address	
  2311                              <1> 	;    r2 - negative word count
  2312                              <1> 	;
  2313                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2314                              <1> 	;
  2315                              <1> 	; INPUTS ->
  2316                              <1> 	;    u.uno - process number (to be swapped out)
  2317                              <1> 	; OUTPUTS ->
  2318                              <1> 	;    none
  2319                              <1> 	;
  2320                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2321                              <1> 	;
  2322 00004635 8B3D[12670000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2323 0000463B B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2324 00004640 BE[C0660000]        <1> 	mov	esi, user ; active user (u) structure	
  2325 00004645 F3A5                <1> 	rep	movsd
  2326                              <1> 	;
  2327 00004647 8B35[C4660000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2328                              <1> 			     ;      points to user registers)
  2329 0000464D 8B0D[C0660000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2330                              <1> 			     ; (for IRET)
  2331                              <1> 			     ; [u.sp] -> EIP (user)
  2332                              <1> 			     ; [u.sp+4]-> CS (user)
  2333                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2334                              <1> 			     ; [u.sp+12] -> ESP (user)
  2335                              <1> 			     ; [u.sp+16] -> SS (user)	
  2336 00004653 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2337 00004655 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2338                              <1> 			     ; (for IRET) 	
  2339 00004658 C1E902              <1> 	shr	ecx, 2	     		
  2340 0000465B F3A5                <1> 	rep	movsd
  2341 0000465D C3                  <1> 	retn
  2342                              <1> 
  2343                              <1> 	; Original UNIX v1 'wswap' routine:
  2344                              <1> 	; wswap:
  2345                              <1> 		; mov *$30,u.emt / determines handling of emts
  2346                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2347                              <1> 				; / illegal instructions
  2348                              <1> 		; mov u.break,r2 / put process program break address in r2
  2349                              <1> 		; inc r2 / add 1 to it 
  2350                              <1> 		; bic $1,r2 / make it even
  2351                              <1> 		; mov r2,u.break / set break to an even location
  2352                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2353                              <1> 			     ; / at moment of swap in r3
  2354                              <1> 		; cmp r2,$core / is u.break less than $core
  2355                              <1> 		; blos 2f / yes
  2356                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2357                              <1>        		; bhis 2f / yes
  2358                              <1> 	; 1:
  2359                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2360                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2361                              <1> 		; bne 1b / no, keep packing
  2362                              <1> 	 	; br 1f / yes
  2363                              <1> 	; 2:
  2364                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2365                              <1> 	; 1:
  2366                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2367                              <1> 			   ; / (user up to end of stack gets written out)
  2368                              <1> 		; neg r2 / make it negative
  2369                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2370                              <1> 		; mov r2,swp+4 / word count
  2371                              <1> 		; movb u.uno,r1 / move user process number to r1
  2372                              <1> 		; asl r1 / x2 for index
  2373                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2374                              <1> 				     ; / into the p.break table
  2375                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2376                              <1> 				    ; /	for process to r1
  2377                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2378                              <1> 			     ; / (block number)
  2379                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2380                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2381                              <1> 	; 1:
  2382                              <1>        		; tstb swp+1 / is lt done writing?
  2383                              <1>        		; bne 1b / no, wait
  2384                              <1> 		; rts r0 / yes, return to swap
  2385                              <1> 
  2386                              <1> rswap:  ; < swap in, swap from disk >
  2387                              <1> 	; 15/09/2015
  2388                              <1> 	; 28/08/2015
  2389                              <1> 	; 14/05/2015
  2390                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2391                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2392                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2393                              <1> 	; from disk into core.
  2394                              <1> 	;
  2395                              <1> 	; Retro UNIX 386 v1 modification ->
  2396                              <1> 	;       User (u) structure content and the user's register content
  2397                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2398                              <1> 	;	saving 'u' structure and user registers for task switching).
  2399                              <1> 	;	u.usp - points to kernel stack address which contains
  2400                              <1> 	;		user's registers while entering system call.  
  2401                              <1> 	;	u.sp  - points to kernel stack address 
  2402                              <1> 	;		to return from system call -for IRET-.
  2403                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2404                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2405                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2406                              <1> 	;
  2407                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2408                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2409                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2410                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2411                              <1> 	;	compatibles was using 1MB segmented memory 
  2412                              <1> 	;	in 8086/8088 times.
  2413                              <1> 	;
  2414                              <1> 	; INPUTS ->
  2415                              <1> 	;    r1 - process number of process to be read in
  2416                              <1> 	;    p.break - negative of word count of process 
  2417                              <1> 	;    p.dska - disk address of the process		
  2418                              <1> 	;    u.emt - determines handling of emt's 	
  2419                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2420                              <1> 	; OUTPUTS ->
  2421                              <1> 	;    8 = (u.ilgins)
  2422                              <1> 	;    24 = (u.emt)
  2423                              <1> 	;    swp - bit 10 is set to indicate read 
  2424                              <1> 	;		(bit 15=0 when reading is done)	
  2425                              <1> 	;    swp+2 - disk block address
  2426                              <1> 	;    swp+4 - negative word count 	
  2427                              <1> 	;      ((swp+6 - address of user structure)) 
  2428                              <1> 	;
  2429                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2430                              <1> 	;
  2431                              <1> 	; INPUTS ->
  2432                              <1> 	;    AL	- new process number (to be swapped in)	 
  2433                              <1> 	; OUTPUTS ->
  2434                              <1> 	;    none
  2435                              <1> 	;
  2436                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2437                              <1> 	;
  2438                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2439 0000465E 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2440 00004660 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2441 00004665 BF[C0660000]        <1> 	mov	edi, user ; active user (u) structure	
  2442 0000466A F3A5                <1> 	rep	movsd
  2443 0000466C 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2444 0000466D 8B3D[C4660000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2445                              <1> 			     ;      points to user registers)
  2446 00004673 8B0D[C0660000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2447                              <1> 			     ; (for IRET)
  2448                              <1> 			     ; [u.sp] -> EIP (user)
  2449                              <1> 			     ; [u.sp+4]-> CS (user)
  2450                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2451                              <1> 			     ; [u.sp+12] -> ESP (user)
  2452                              <1> 			     ; [u.sp+16] -> SS (user)		
  2453                              <1> 	; 28/08/2015
  2454 00004679 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2455 0000467B 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2456                              <1> 			     ; (for IRET) 	
  2457 0000467E C1E902              <1> 	shr	ecx, 2	       		
  2458 00004681 F3A5                <1> 	rep	movsd
  2459 00004683 8B25[C4660000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2460 00004689 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2461 0000468A C3                  <1> 	retn
  2462                              <1> 
  2463                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2464                              <1> 	;rswap:
  2465                              <1>        		; asl r1 / process number x2 for index
  2466                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2467                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2468                              <1>        		; bis $2000,swp / read
  2469                              <1>        		; jsr r0,ppoke / read it in 
  2470                              <1> 	; 1:
  2471                              <1>        		; tstb swp+1 / done
  2472                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2473                              <1>        		; mov u.emt,*$30 / yes move these
  2474                              <1>        		; mov u.ilgins,*$10 / back
  2475                              <1>        		; rts r0 / return
  2476                              <1> 
  2477                              <1> 	;unpack: ; / move stack back to its normal place
  2478                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2479                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2480                              <1> 		; blos 2f / yes, return
  2481                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2482                              <1> 			     ; / before swapping
  2483                              <1> 		; bhis 2f / yes, return
  2484                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2485                              <1> 		; add r3,r2
  2486                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2487                              <1> 	; 1:
  2488                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2489                              <1> 		; cmp r2,u.break / in core
  2490                              <1> 		; bne 1b
  2491                              <1> 	; 2:
  2492                              <1>        		; rts r0
  2493                              <1> 
  2494                              <1> putlu: 
  2495                              <1> 	; 12/09/2015
  2496                              <1> 	; 02/09/2015
  2497                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2498                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2499                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2500                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2501                              <1> 	; the last process on the queue to process in r1 by putting
  2502                              <1> 	; the process number in r1 into the last process's link.
  2503                              <1> 	;
  2504                              <1> 	; INPUTS ->
  2505                              <1> 	;    r1 - user process number
  2506                              <1> 	;    r2 - points to lowest priority queue 
  2507                              <1> 	;    p.dska - disk address of the process		
  2508                              <1> 	;    u.emt - determines handling of emt's 	
  2509                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2510                              <1> 	; OUTPUTS ->
  2511                              <1> 	;    r3 - process number of last process on the queue upon
  2512                              <1> 	;	  entering putlu
  2513                              <1> 	;    p.link-1 + r3 - process number in r1
  2514                              <1> 	;    r2 - points to lowest priority queue
  2515                              <1> 	;
  2516                              <1> 	; ((Modified registers: EDX, EBX)) 
  2517                              <1> 	;
  2518                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2519                              <1> 
  2520                              <1> 	; eBX = r2
  2521                              <1> 	; eAX = r1 (AL=r1b)
  2522                              <1> 
  2523 0000468B BB[BA660000]        <1> 	mov	ebx, runq
  2524 00004690 0FB613              <1> 	movzx  	edx, byte [ebx]
  2525 00004693 43                  <1> 	inc	ebx
  2526 00004694 20D2                <1> 	and	dl, dl
  2527                              <1> 		; tstb (r2)+ / is queue empty?
  2528 00004696 740A                <1>        	jz	short putlu_1
  2529                              <1> 		; beq 1f / yes, branch
  2530 00004698 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2531                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2532                              <1> 			     ; / in r3
  2533 0000469A 8882[33640000]      <1>        	mov	[edx+p.link-1], al
  2534                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2535                              <1> 			     ; / "last users" link
  2536 000046A0 EB03                <1> 	jmp	short putlu_2
  2537                              <1> 		; br 2f /
  2538                              <1> putlu_1: ; 1:
  2539 000046A2 8843FF              <1> 	mov	[ebx-1], al
  2540                              <1>        		; movb r1,-1(r2) / user is only user; 
  2541                              <1> 			    ; / put process no. at beginning and at end
  2542                              <1> putlu_2: ; 2: 
  2543 000046A5 8803                <1> 	mov	[ebx], al
  2544                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2545                              <1> 			     ; / on the queue
  2546 000046A7 88C2                <1> 	mov	dl, al
  2547 000046A9 88B2[33640000]      <1>         mov     [edx+p.link-1], dh ; 0
  2548                              <1> 		; dec r2 / restore r2
  2549 000046AF C3                  <1>         retn
  2550                              <1> 		; rts r0
  2551                              <1> 
  2552                              <1> ;copyz:
  2553                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2554                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2555                              <1> ;       mov     (r0)+,r1
  2556                              <1> ;       mov     (r0)+,r2
  2557                              <1> ;1:
  2558                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2559                              <1> ;       cmp     r1,r2 
  2560                              <1> ;       blo     1b
  2561                              <1> ;       mov     (sp)+,r2 / restore r2
  2562                              <1> ;       mov     (sp)+,r1 / restore r1
  2563                              <1> ;       rts     r0 
  2564                              <1> 
  2565                              <1> idle:
  2566                              <1> 	; 01/09/2015
  2567                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2568                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2569                              <1> 	; (idle & wait loop)
  2570                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2571                              <1> 	; idle procedure!
  2572                              <1>       	;
  2573                              <1>   	; 01/09/2015
  2574 000046B0 FB                  <1> 	sti
  2575                              <1>       	; 29/07/2013
  2576 000046B1 F4                  <1>       	hlt
  2577 000046B2 90                  <1>       	nop ; 10/10/2013
  2578 000046B3 90                  <1>       	nop
  2579 000046B4 90                  <1>       	nop
  2580                              <1>       	; 23/10/2013
  2581 000046B5 90                  <1>       	nop
  2582 000046B6 90                  <1>       	nop
  2583 000046B7 90                  <1>       	nop
  2584 000046B8 90                  <1>       	nop
  2585 000046B9 C3                  <1>       	retn      
  2586                              <1> 
  2587                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2588                              <1> 	;clr *$ps / clear ps
  2589                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2590                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2591                              <1> 	;1 / wait for interrupt
  2592                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2593                              <1> 	;mov (sp)+,*$ps
  2594                              <1> 	;rts r0
  2595                              <1> 
  2596                              <1> clear:
  2597                              <1> 	; 03/02/2022
  2598                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2599                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2600                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2601                              <1> 	; on the current device (cdev)
  2602                              <1> 	;	
  2603                              <1> 	; INPUTS ->
  2604                              <1> 	;    r1 - block number of block to be zeroed
  2605                              <1> 	;    cdev - current device number 
  2606                              <1> 	; OUTPUTS ->
  2607                              <1> 	;    a zeroed I/O buffer onto the current device
  2608                              <1> 	;    r1 - points to last entry in the I/O buffer
  2609                              <1> 	;
  2610                              <1> 	; ((AX = R1)) input/output
  2611                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2612                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2613                              <1> 
  2614 000046BA E8A20E0000          <1> 	call 	wslot
  2615                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2616                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2617 000046BF 89DF                <1> 	mov	edi, ebx ; r5
  2618 000046C1 89C2                <1> 	mov	edx, eax
  2619 000046C3 B980000000          <1> 	mov	ecx, 128
  2620                              <1> 		; mov $256.,r3
  2621 000046C8 31C0                <1> 	xor	eax, eax
  2622 000046CA F3AB                <1> 	rep	stosd
  2623 000046CC 89D0                <1> 	mov	eax, edx
  2624                              <1> ; 1: 
  2625                              <1>        		; clr (r5)+ / zero data word in buffer
  2626                              <1>        		; dec r3
  2627                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2628                              <1> 	;call	dskwr
  2629                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2630                              <1>                              ; / block specified in r1
  2631                              <1> 	; eAX (r1) = block number
  2632                              <1> 	;retn
  2633                              <1> 		; rts r0
  2634                              <1> 	; 03/02/2022
  2635 000046CE E9AA0E0000          <1> 	jmp	dskwr
  2052                                  %include 'u4.s'        ; 15/04/2015
  2053                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2054                              <1> ; Last Modification: 26/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 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2065                              <1> ;
  2066                              <1> ; ****************************************************************************
  2067                              <1> ; 14/10/2015
  2068                              <1> 
  2069                              <1> ;setisp:
  2070                              <1>        ;mov     r1,-(sp)
  2071                              <1>        ;mov     r2,-(sp)
  2072                              <1>        ;mov     r3,-(sp)
  2073                              <1>        ;mov     clockp,-(sp)
  2074                              <1>        ;mov     $s.syst+2,clockp
  2075                              <1>        ;jmp     (r0)
  2076                              <1> 
  2077                              <1> clock: ; / interrupt from 60 cycle clock
  2078                              <1> 	
  2079                              <1> 	; 14/10/2015
  2080                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2081                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2082                              <1> 
  2083                              <1>        ;mov     r0,-(sp) / save r0
  2084                              <1>        ;tst     *$lks / restart clock?
  2085                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2086                              <1>        ;inc     (r0)
  2087                              <1>        ;bne     1f
  2088                              <1>        ;inc     -(r0)
  2089                              <1> ;1:
  2090                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2091                              <1>        ;inc     (r0)
  2092                              <1>        ;bne     1f
  2093                              <1>        ;inc     -(r0)
  2094                              <1> ;1:
  2095                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2096                              <1> 
  2097 000046D3 803D[04670000]00    <1> 	cmp	byte [u.quant], 0
  2098 000046DA 772C                <1> 	ja	short clk_1
  2099                              <1> 	;
  2100 000046DC 803D[BF660000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2101 000046E3 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2102 000046E5 803D[11670000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2103 000046EC 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2104 000046EE 66833D[06670000]00  <1> 	cmp	word [u.intr], 0
  2105 000046F6 7616                <1> 	jna	short clk_2
  2106                              <1> clk_0:
  2107                              <1> 	; 14/10/2015
  2108 000046F8 FE05[BF660000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2109 000046FE 58                  <1> 	pop	eax ; return address to the timer interrupt
  2110                              <1> 	;
  2111 000046FF B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2112                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2113 00004701 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2114                              <1> 	;
  2115 00004703 E97CEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2116                              <1> clk_1:
  2117 00004708 FE0D[04670000]      <1> 	dec	byte [u.quant]
  2118                              <1> clk_2:
  2119 0000470E C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2120                              <1> 
  2121                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2122                              <1> 
  2123                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2124                              <1>        ;decb    (r0)
  2125                              <1>        ;bge     1f / if less than 0
  2126                              <1>        ;clrb    (r0) / make it 0
  2127                              <1> ;1: / decrement time out counts return now if priority was not 0
  2128                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2129                              <1>        ;bge     2f / yes, check time outs
  2130                              <1>        ;tstb    (r0) / no, user timed out?
  2131                              <1>        ;bne     1f / no
  2132                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2133                              <1>        ;bne     1f / no, 1f
  2134                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2135                              <1>        ;sys     0 / sysrele
  2136                              <1>        ;rti
  2137                              <1> ;2: / priority is high so just decrement time out counts
  2138                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2139                              <1> ;2:
  2140                              <1>        ;tstb    (r0) / is the time out?
  2141                              <1>        ;beq     3f / yes, 3f (get next entry)
  2142                              <1>        ;decb    (r0) / no, decrement the time
  2143                              <1>        ;bne     3f / isit zero now?
  2144                              <1>        ;incb    (r0) / yes, increment the time
  2145                              <1> ;3:
  2146                              <1>        ;inc     r0 / next entry
  2147                              <1>        ;cmp     r0,$touts / end of toutt table?
  2148                              <1>        ;blo     2b / no, check this entry
  2149                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2150                              <1>        ;rti / return from interrupt
  2151                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2152                              <1>        ;mov     (sp)+,r0 / restore r0
  2153                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2154                              <1>        ;jsr     r0,setisp / save registers
  2155                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2156                              <1>                                ;  / the table
  2157                              <1> ;1:
  2158                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2159                              <1>        ;beq     2f / yes
  2160                              <1>        ;decb    toutt(r0) / no, decrement the time
  2161                              <1>        ;bne     2f / is the time 0, now
  2162                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2163                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2164                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2165                              <1> ;2:
  2166                              <1>        ;dec     r0 / set up r0 for next entry
  2167                              <1>        ;bge     1b / finished? , no, go back
  2168                              <1>        ;br      retisp / yes, restore registers and do a rti
  2169                              <1> 
  2170                              <1> ;retisp:
  2171                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2172                              <1>        ;mov     (sp)+,r3
  2173                              <1>        ;mov     (sp)+,r2
  2174                              <1>        ;mov     (sp)+,r1
  2175                              <1>        ;mov     (sp)+,r0
  2176                              <1>        ;rti     / return from interrupt
  2177                              <1> 
  2178                              <1> 
  2179                              <1> wakeup: ; / wakeup processes waiting for an event 
  2180                              <1> 	; / by linking them to the queue
  2181                              <1> 	;
  2182                              <1> 	; 26/02/2022
  2183                              <1> 	; 15/09/2015
  2184                              <1> 	; 29/06/2015
  2185                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2186                              <1> 	;
  2187                              <1> 	; 15/05/2013 - 02/06/2014
  2188                              <1> 	; Retro UNIX 8086 v1 modification !
  2189                              <1> 	; (Process/task switching routine by using
  2190                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2191                              <1> 	;
  2192                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2193                              <1> 	; sleeping in the specified wait channel by creating a link 
  2194                              <1> 	; to it from the last user process on the run queue.
  2195                              <1> 	; If there is no process to wake up, nothing happens.
  2196                              <1> 	;
  2197                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2198                              <1> 	; 'switching' status of the current process (owns current tty)
  2199                              <1> 	; (via alt + function keys) to a process which has highest
  2200                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2201                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2202                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2203                              <1> 	; tty for tty switching by keyboard.)	 
  2204                              <1> 	; 
  2205                              <1> 	; INPUT -> 
  2206                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2207                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2208                              <1> 	;
  2209                              <1> 	; ((modified registers: EAX, EBX))
  2210                              <1> 	;
  2211 0000470F 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2212 00004712 81C3[68630000]      <1> 	add	ebx, wlist
  2213 00004718 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2214 0000471A 20C0                <1> 	and	al, al
  2215 0000471C 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2216                              <1> 	;
  2217 0000471E 30E4                <1> 	xor	ah, ah
  2218 00004720 8825[04670000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2219 00004726 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2220                              <1> 	; 15/09/2015
  2221 00004728 0FB6D8              <1> 	movzx	ebx, al
  2222                              <1> 	; 26/02/2022 (p.waitc is not used)
  2223                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2224 0000472B FEC4                <1> 	inc	ah
  2225 0000472D 88A3[43640000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2226                              <1> 	;
  2227 00004733 57                  <1> 	push	edi
  2228 00004734 52                  <1> 	push	edx
  2229 00004735 E851FFFFFF          <1> 	call	putlu
  2230 0000473A 5A                  <1> 	pop	edx
  2231 0000473B 5F                  <1> 	pop	edi
  2232                              <1> wa0:
  2233 0000473C C3                  <1> 	retn
  2234                              <1> 
  2235                              <1> sleep: 
  2236                              <1> 	; 26/02/2022
  2237                              <1> 	; 03/02/2022
  2238                              <1> 	; 15/09/2015
  2239                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2240                              <1> 	;
  2241                              <1> 	; 09/05/2013 - 20/03/2014
  2242                              <1> 	;
  2243                              <1> 	; Retro UNIX 8086 v1 modification !
  2244                              <1> 	; (Process/task switching and quit routine by using
  2245                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2246                              <1> 	;
  2247                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2248                              <1> 	; tty and tape output or input becomes available
  2249                              <1> 	; and process is put on waiting channel and swapped out,
  2250                              <1> 	; then -when the tty or tape is ready to write or read-
  2251                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2252                              <1> 	;
  2253                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2254                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2255                              <1> 	; status of the current process also INT 1Ch will count down
  2256                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2257                              <1> 	; to tty buffer of the current process and kernel will get
  2258                              <1> 	; user input by using tty buffer of the current process
  2259                              <1> 	; (instead of standard INT 16h interrupt).
  2260                              <1> 	; TTY output will be redirected to related video page of text mode
  2261                              <1> 	; (INT 10h will be called with different video page depending
  2262                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2263                              <1> 	; pseudo screens.)
  2264                              <1> 	;
  2265                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2266                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2267                              <1> 	; characters/data on serial port(s).
  2268                              <1> 	;
  2269                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2270                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2271                              <1> 	; 
  2272                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2273                              <1> 	;
  2274                              <1> 	;; 05/10/2013
  2275                              <1>         ;10/12/2013
  2276                              <1> 	;cmp   byte [u.uno], 1
  2277                              <1>         ;ja    short sleep0
  2278                              <1> 	;retn
  2279                              <1> 
  2280                              <1> 	; 20/03/2014
  2281                              <1> 	;mov	bx, [runq]
  2282                              <1> 	;cmp	bl, bh
  2283                              <1> 	;jne	short sleep0	
  2284                              <1> 	; 25/02/2014
  2285                              <1> 	;cmp word ptr [runq], 0
  2286                              <1> 	;ja short sleep0	
  2287                              <1> 	;retn
  2288                              <1> sleep0:
  2289                              <1> 	;
  2290 0000473D E849000000          <1> 	call	isintr
  2291                              <1> 	;jnz	sysret
  2292                              <1> 		; / wait for event
  2293                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2294                              <1> 			      ; / or quit from user
  2295                              <1>                		; br 2f / something happened
  2296                              <1> 			      ; / yes, his interrupt so return
  2297                              <1>                      	      ;	/ to user
  2298                              <1> 	; 03/02/2022
  2299 00004742 7405                <1> 	jz	short sleep_2
  2300                              <1> sleep_3:
  2301 00004744 E9DFEAFFFF          <1> 	jmp	sysret
  2302                              <1> sleep_2:
  2303                              <1> 	; 30/06/2015
  2304 00004749 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2305 0000474C 81C3[68630000]      <1> 	add	ebx, wlist
  2306 00004752 8A03                <1> 	mov	al, [ebx]
  2307 00004754 20C0                <1> 	and	al, al
  2308 00004756 7407                <1> 	jz	short sleep1
  2309 00004758 53                  <1> 	push	ebx
  2310 00004759 E82DFFFFFF          <1> 	call	putlu
  2311 0000475E 5B                  <1> 	pop	ebx
  2312                              <1> sleep1:
  2313 0000475F A0[11670000]        <1> 	mov	al, [u.uno]    
  2314 00004764 8803                <1>   	mov	[ebx], al 	; put the process number
  2315                              <1> 				; in the wait channel
  2316                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2317                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2318                              <1> 				     ; / on the stack
  2319                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2320                              <1> 				     ; / to put to sleep in there
  2321                              <1>         ; 15/09/2015
  2322 00004766 0FB6D8              <1> 	movzx	ebx, al
  2323 00004769 C683[43640000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2324                              <1> 	; 26/02/2022 (p.waitc is not used)
  2325                              <1> 	;inc	ah
  2326                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2327                              <1> 	;
  2328 00004770 66FF35[AC660000]    <1> 	push    word [cdev]
  2329                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2330 00004777 E842FEFFFF          <1> 	call	swap
  2331                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2332 0000477C 668F05[AC660000]    <1>         pop     word [cdev]
  2333                              <1> 		; mov (sp)+,cdev / restore device
  2334 00004783 E803000000          <1> 	call	isintr
  2335                              <1> 	; 22/09/2013
  2336                              <1> 	;jnz	sysret         
  2337                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2338                              <1>                		; br 2f / yes, return to new user
  2339                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2340                              <1> 				; / originally on the wait channel
  2341                              <1>        		; beq 1f / if 0 branch
  2342                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2343                              <1>        		; mov $300,*$ps / processor priority = 6
  2344                              <1> 		; jsr r0,putlu / create link to old process number
  2345                              <1>        		; clr *$ps / clear the status; process priority = 0
  2346                              <1> 	; 03/02/2022
  2347 00004788 75BA                <1> 	jnz	short sleep_3
  2348                              <1>      ;1:
  2349 0000478A C3                  <1> 	retn
  2350                              <1> 		; rts r0 / return
  2351                              <1>      ;2:
  2352                              <1>         ;;jmp	sysret
  2353                              <1> 		; jmp sysret / return to user
  2354                              <1> 
  2355                              <1> isintr:
  2356                              <1> 	; 03/02/2022
  2357                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2358                              <1> 	;
  2359                              <1> 	; 09/05/2013 - 30/05/2014
  2360                              <1> 	;
  2361                              <1> 	; Retro UNIX 8086 v1 modification !
  2362                              <1> 	; (Process/task switching and quit routine by using
  2363                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2364                              <1> 	;
  2365                              <1> 	; Retro UNIX 8086 v1 modification:
  2366                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2367                              <1> 	;  and there is a 'quit' request by user;
  2368                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2369                              <1> 	;  "nothing to do". (20/10/2013)
  2370                              <1> 	;
  2371                              <1> 	; 20/10/2013
  2372 0000478B 66833D[F8660000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2373 00004793 761F                <1> 	jna	short isintr2 ; retn
  2374                              <1> 	; 03/09/2013
  2375                              <1> 	; (nothing to do)
  2376                              <1> 	;retn
  2377                              <1> 	; 22/09/2013
  2378 00004795 66833D[06670000]00  <1> 	cmp	word [u.intr], 0
  2379 0000479D 7615                <1> 	jna	short isintr2 ; retn
  2380                              <1> 	; 30/05/2014
  2381                              <1> 	;push	ax
  2382                              <1> 	; 03/02/2022
  2383 0000479F 50                  <1> 	push	eax
  2384 000047A0 66A1[08670000]      <1> 	mov	ax, [u.quit]
  2385 000047A6 6609C0              <1> 	or	ax, ax ; 0 ?
  2386 000047A9 7408                <1> 	jz	short isintr1 ; zf = 1
  2387 000047AB 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2388 000047AF 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2389                              <1> 	;xor	ax, ax ; zf = 1
  2390                              <1> 	; 03/02/2022
  2391 000047B1 31C0                <1> 	xor	eax, eax ; zf = 1
  2392                              <1> isintr1:
  2393                              <1> 	;pop	ax
  2394                              <1> 	; 03/02/2022
  2395 000047B3 58                  <1> 	pop	eax
  2396                              <1> isintr2: ; 22/09/2013
  2397                              <1> 	; zf=1 -> nothing to do
  2398 000047B4 C3                  <1> 	retn
  2399                              <1> 
  2400                              <1> 	; UNIX v1 original 'isintr' routine... 
  2401                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2402                              <1>        	;mov     r2,-(sp) / save r2
  2403                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2404                              <1>         ;                 / typewriter
  2405                              <1>        	;beq     1f / if 0, do nothing except skip return
  2406                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2407                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2408                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2409                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2410                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2411                              <1>         ;              / of interrupts
  2412                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2413                              <1>      ;1:
  2414                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2415                              <1>      ;4:
  2416                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2417                              <1>        	;mov     (sp)+,r1
  2418                              <1>        	;rts     r0
  2419                              <1>      ;3: / interrupt char = quit (fs)
  2420                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2421                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2422                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2423                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2424                              <1>      ;1: / find process control tty entry in tty block
  2425                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2426                              <1>        	;beq     1f / block found go to 1f
  2427                              <1>        	;add     $8,r1 / look at next tty block
  2428                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2429                              <1>        	;blo     1b / no
  2430                              <1>        	;br      4b / no process control tty found so go to 4b
  2431                              <1>      ;1:
  2432                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2433                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2434                              <1>         ;                  / identifier
  2435                              <1>        	;inc     0f / increment
  2436                              <1>      ;1:
  2437                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2438                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2439                              <1>         ;             / being typed out after you hit the interrupt
  2440                              <1>         ;             / key
  2441                              <1>        	;br      1b
  2053                                  %include 'u5.s'        ; 03/06/2015
  2054                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2055                              <1> ; Last Modification: 22/04/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 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2066                              <1> ;
  2067                              <1> ; ****************************************************************************
  2068                              <1> ; 14/11/2015
  2069                              <1> 
  2070                              <1> mget:
  2071                              <1> 	; 22/04/2022
  2072                              <1> 	; 03/02/2022
  2073                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2074                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2075                              <1> 	;
  2076                              <1> 	; Get existing or (allocate) a new disk block for file
  2077                              <1> 	; 
  2078                              <1> 	; INPUTS ->
  2079                              <1> 	;    u.fofp (file offset pointer)
  2080                              <1> 	;    inode 
  2081                              <1> 	;    u.off (file offset)
  2082                              <1> 	; OUTPUTS ->
  2083                              <1> 	;    r1 (physical block number)
  2084                              <1> 	;    r2, r3, r5 (internal)
  2085                              <1> 	;
  2086                              <1> 	; ((AX = R1)) output
  2087                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2088                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2089                              <1> 
  2090                              <1> 		; mov *u.fofp,mq / file offset in mq
  2091                              <1> 		; clr ac / later to be high sig
  2092                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2093                              <1> 		; mov mq,r2
  2094                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2095                              <1> 		; bne 4f / branch for large file
  2096                              <1> mget_0:	
  2097                              <1> 	; 03/02/2022
  2098 000047B5 29C0                <1> 	sub	eax, eax
  2099 000047B7 29D2                <1> 	sub	edx, edx
  2100 000047B9 29C9                <1> 	sub	ecx, ecx
  2101 000047BB 29DB                <1> 	sub	ebx, ebx
  2102                              <1> 
  2103 000047BD 8B35[D8660000]      <1>         mov     esi, [u.fofp]
  2104                              <1>         ;movzx	ebx, byte [esi+1]
  2105                              <1> 	; 03/02/2022
  2106 000047C3 46                  <1> 	inc	esi
  2107 000047C4 8A1E                <1> 	mov	bl, [esi]
  2108                              <1> 
  2109                              <1> 	; BX = r2
  2110                              <1> 	; 03/02/2022
  2111 000047C6 F605[C5630000]10    <1> 	test	byte [i.flgs+1], 10h
  2112                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2113                              <1> 			  	     ; is this a large or small file
  2114 000047CD 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2115                              <1> 
  2116 000047CF F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2117                              <1> 		; bit $!17,r2
  2118 000047D2 7525                <1> 	jnz 	short mget_2
  2119                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2120 000047D4 80E30E              <1>         and     bl, 0Eh  
  2121                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2122                              <1> 	; 03/02/2022
  2123 000047D7 668B83[CA630000]    <1> 	mov	ax, [ebx+i.dskp]
  2124                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2125                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2126                              <1> 	; 03/02/2022
  2127 000047DE 09C0                <1> 	or	eax, eax
  2128                              <1> 	;or 	ax, ax
  2129 000047E0 7516                <1> 	jnz 	short mget_1 
  2130                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2131                              <1> 		       ; / for file
  2132 000047E2 E8A6000000          <1> 	call 	alloc
  2133                              <1> 		; jsr r0,alloc / allocate a new block
  2134                              <1>          ; eAX (r1) = Physical block number
  2135 000047E7 668983[CA630000]    <1> 	mov 	[ebx+i.dskp], ax
  2136                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2137 000047EE E835020000          <1> 	call 	setimod	
  2138                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2139 000047F3 E8C2FEFFFF          <1> 	call	clear
  2140                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2141                              <1> mget_1: ; 2:
  2142                              <1>         ; eAX (r1) = Physical block number
  2143 000047F8 C3                  <1> 	retn 
  2144                              <1> 		; rts r0
  2145                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2146 000047F9 E88F000000          <1> 	call 	alloc
  2147                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2148                              <1> 	                     ; / block number in r1
  2149                              <1>         ; eAX (r1) = Physical block number
  2150 000047FE E85E0D0000          <1> 	call 	wslot
  2151                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2152                              <1> 			     ; / first data word in buffer
  2153                              <1>         ; 03/02/2022
  2154 00004803 31C9                <1> 	xor	ecx, ecx
  2155 00004805 B108                <1> 	mov	cl, 8
  2156                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2157                              <1> 		   ; into new indirect block area for the new
  2158                              <1> 		   ; large file		
  2159 00004807 89DF                <1> 	mov 	edi, ebx ; r5
  2160 00004809 BE[CA630000]        <1> 	mov 	esi, i.dskp 
  2161                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2162                              <1> 			   ; / block pointers
  2163                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2164                              <1> 			  ; / large file
  2165                              <1> 	; 22/04/2022
  2166 0000480E 50                  <1> 	push	eax ; * ; bugfix
  2167                              <1> 
  2168                              <1> 	;xor 	ax, ax ; mov ax, 0
  2169                              <1> 	; 03/02/2022
  2170 0000480F 31C0                <1> 	xor	eax, eax
  2171                              <1> mget_3: ;1:
  2172 00004811 66A5                <1> 	movsw
  2173                              <1> 		; mov (r2),(r5)+
  2174 00004813 668946FE            <1> 	mov 	[esi-2], ax
  2175                              <1> 		; clr (r2)+
  2176 00004817 E2F8                <1> 	loop	mget_3 ; 1b
  2177                              <1> 		; dec r3
  2178                              <1> 		; bgt 1b
  2179                              <1> 
  2180 00004819 B1F8                <1> 	mov 	cl, 256-8
  2181                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2182                              <1> mget_4:	; 1
  2183 0000481B F366AB              <1> 	rep 	stosw
  2184                              <1> 		; clr (r5)+
  2185                              <1> 		; dec r3
  2186                              <1> 		; bgt 1b
  2187                              <1> 	
  2188                              <1> 	; 22/04/2022
  2189                              <1> 	;pop	eax ; * ; bugfix
  2190                              <1> 
  2191                              <1> 	; 24/03/2013
  2192                              <1>         ; AX (r1) = Physical block number
  2193 0000481E E85A0D0000          <1> 	call	dskwr
  2194                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2195                              <1> 
  2196                              <1> 	; 22/04/2022
  2197 00004823 58                  <1> 	pop	eax ; * ; bugfix
  2198                              <1> 
  2199                              <1>         ; eAX (r1) = Physical block number
  2200 00004824 66A3[CA630000]      <1> 	mov 	[i.dskp], ax
  2201                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2202                              <1> 	; 03/02/2022
  2203 0000482A 800D[C5630000]10    <1> 	or	byte [i.flgs+1], 10h
  2204                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2205                              <1> 		; bis $10000,i.flgs / set large file bit 
  2206                              <1> 				  ; / in i.flgs word of i-node
  2207 00004831 E8F2010000          <1> 	call	setimod
  2208                              <1> 		; jsr r0,setimod / set i-node modified flag
  2209 00004836 E97AFFFFFF          <1>         jmp     mget_0 
  2210                              <1> 		; br mget
  2211                              <1> 
  2212                              <1> mget_5:  ; 4 ; large file
  2213                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2214                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2215                              <1> 			    ; / in indirect block
  2216                              <1> 		; mov r2,-(sp) / save on stack (*)
  2217                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2218                              <1>        		          ; / indirect block
  2219                              <1> 		; bic $!16,r2
  2220 0000483B 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2221 0000483E 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2222                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2223                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2224                              <1> 	; There is always 1 indirect block for this file system
  2225                              <1> 	; 03/02/2022
  2226 0000483F 66A1[CA630000]      <1> 	mov	ax, [i.dskp]
  2227                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2228                              <1> 		; mov i.dskp(r2),r1
  2229                              <1> 	; 03/02/2022
  2230 00004845 09C0                <1> 	or	eax, eax
  2231                              <1> 	;or 	ax, ax ; R1
  2232 00004847 7515                <1> 	jnz 	short mget_6 ; 2f
  2233                              <1> 		; bne 2f / if no indirect block exists
  2234 00004849 E83F000000          <1> 	call 	alloc
  2235                              <1> 		; jsr r0,alloc / allocate a new block
  2236 0000484E 66A3[CA630000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2237                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2238 00004854 E8CF010000          <1> 	call 	setimod
  2239                              <1> 		; jsr r0,setimod / set i-node modified byte
  2240                              <1> 	; eAX = new block number
  2241 00004859 E85CFEFFFF          <1> 	call 	clear
  2242                              <1> 		; jsr r0,clear / clear new block
  2243                              <1> mget_6: ;2
  2244                              <1> 	; 05/03/2013
  2245                              <1> 	; eAX = r1, physical block number (of indirect block)
  2246 0000485E E88C0C0000          <1> 	call 	dskrd ; read indirect block
  2247                              <1> 		; jsr r0,dskrd / read in indirect block
  2248 00004863 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2249                              <1> 		; mov (sp)+,r2 / get offset
  2250                              <1> 	; eAX = r1, physical block number (of indirect block)
  2251 00004864 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2252                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2253                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2254 00004865 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2255                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2256                              <1> 	                  ; / points to location of inter
  2257                              <1> 	; 03/02/2022
  2258 00004867 668B03              <1> 	mov	ax, [ebx]
  2259                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2260                              <1> 			      ; in file sought in R1 (AX)
  2261                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2262                              <1> 	               	    ; / sought in r1
  2263                              <1> 	; 03/02/2022
  2264 0000486A 09C0                <1> 	or	eax, eax
  2265                              <1> 	;or 	ax, ax
  2266 0000486C 751D                <1>         jnz 	short mget_7 ; 2f
  2267                              <1> 		; bne 2f / if no block exists 
  2268 0000486E E81A000000          <1> 	call 	alloc
  2269                              <1> 		; jsr r0,alloc / allocate a new block
  2270 00004873 668903              <1> 	mov 	[ebx], ax ; R1
  2271                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2272                              <1> 	                    ; / indirect block
  2273 00004876 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2274                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2275 00004877 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2276 00004878 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2277 00004879 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2278                              <1> 		; mov (r2),-(sp) / save block number of new block
  2279                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2280 0000487B E8E10C0000          <1> 	call 	wslot
  2281                              <1> 		; jsr r0,wslot
  2282                              <1>         ; eAX (r1) = physical block number
  2283                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2284 00004880 E8F80C0000          <1> 	call 	dskwr
  2285                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2286                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2287                              <1> 			     ; / back out on disk
  2288 00004885 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2289                              <1> 		; mov (sp),r1 / restore block number of new block	
  2290                              <1> 	; eAX (r1) = physical block number of new block
  2291 00004886 E82FFEFFFF          <1> 	call 	clear
  2292                              <1> 		; jsr r0,clear / clear new block	
  2293                              <1> mget_7: ; 2
  2294 0000488B 5A                  <1> 	pop 	edx ; **
  2295                              <1> 		; tst (sp)+ / bump stack pointer
  2296                              <1> 	; eAX (r1) = Block number of new block
  2297 0000488C C3                  <1> 	retn
  2298                              <1> 		; rts r0
  2299                              <1> 
  2300                              <1> alloc:
  2301                              <1> 	; 03/02/2022
  2302                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2303                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2304                              <1> 	;
  2305                              <1> 	; get a free block and 
  2306                              <1> 	; set the corresponding bit in the free storage map
  2307                              <1> 	; 
  2308                              <1> 	; INPUTS ->
  2309                              <1> 	;    cdev (current device)
  2310                              <1> 	;    r2 
  2311                              <1> 	;    r3
  2312                              <1> 	; OUTPUTS ->
  2313                              <1> 	;    r1 (physical block number of block assigned)
  2314                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2315                              <1> 	;
  2316                              <1> 	; ((AX = R1)) output
  2317                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2318                              <1>         ;    ((Modified registers: DX, CX))  
  2319                              <1> 
  2320                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2321                              <1> 		;mov r3,-(sp)
  2322                              <1> 	;push 	ecx
  2323 0000488D 53                  <1> 	push 	ebx ; R2
  2324                              <1> 	;push 	edx ; R3
  2325 0000488E BB[80730000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2326                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2327 00004893 803D[AC660000]00    <1> 	cmp 	byte [cdev], 0
  2328                              <1> 		; tst cdev
  2329 0000489A 7605                <1> 	jna	short alloc_1
  2330                              <1> 		; beq 1f / drum is device
  2331 0000489C BB[88750000]        <1> 	mov	ebx, mount
  2332                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2333                              <1> 			      ; / free storage map
  2334                              <1> alloc_1: ; 1
  2335                              <1> 	; 03/02/2022
  2336                              <1> 	;sub	ecx, ecx
  2337                              <1> 	;sub	edx, edx
  2338                              <1> 	;sub	eax, eax
  2339                              <1> 
  2340 000048A1 668B0B              <1>         mov	cx, [ebx]
  2341                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2342                              <1> 			     ; / storage map
  2343                              <1> 	; 03/02/2022
  2344 000048A4 C1E103              <1> 	shl	ecx, 3
  2345                              <1> 	;shl	cx, 3
  2346                              <1> 		; asl r1 / multiply r1 by eight gives 
  2347                              <1> 		; number of blocks in device
  2348                              <1> 		; asl r1
  2349                              <1> 		; asl r1
  2350                              <1> 	;;push	cx ;; 01/08/2013
  2351                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2352 000048A7 31C0                <1> 	xor 	eax, eax ; 0
  2353                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2354                              <1> alloc_2: ; 1
  2355 000048A9 43                  <1> 	inc 	ebx ; 18/8/2012
  2356 000048AA 43                  <1> 	inc 	ebx ; 
  2357 000048AB 668B13              <1> 	mov 	dx, [ebx]
  2358                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2359                              <1> 	; 03/02/2022
  2360 000048AE 09D2                <1> 	or	edx, edx
  2361                              <1> 	;or 	dx, dx
  2362 000048B0 750D                <1> 	jnz 	short alloc_3 ; 1f
  2363                              <1> 		; bne 1f / branch if any free blocks in this word	
  2364 000048B2 6683C010            <1> 	add 	ax, 16
  2365                              <1> 		; add $16.,r1
  2366                              <1> 	; 03/02/2022
  2367 000048B6 39C8                <1> 	cmp	eax, ecx
  2368                              <1> 	;cmp 	ax, cx    
  2369                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2370 000048B8 72EF                <1> 	jb 	short alloc_2
  2371                              <1> 		; blo 1b
  2372                              <1> 	; 14/11/2015
  2373                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2374                              <1> 	;	because of a (DMA or another) r/w error, 
  2375                              <1> 	;	we will be here, at 'jmp panic' code address,
  2376                              <1> 	;	even if the (disk) file system space is not full !!!
  2377                              <1> 	;	(cx = 0)	
  2378                              <1> 	;
  2379 000048BA E908E2FFFF          <1> 	jmp     panic 
  2380                              <1> 		; jmp panic / found no free storage
  2381                              <1> alloc_3: ; 1
  2382                              <1> 	; 03/02/2022
  2383 000048BF D1EA                <1> 	shr	edx, 1
  2384                              <1> 	;shr	dx, 1
  2385                              <1> 		; asr r3 / find a free block
  2386 000048C1 7203                <1> 	jc	short alloc_4 ; 1f
  2387                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2388                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2389                              <1> 	; 03/02/2022
  2390 000048C3 40                  <1> 	inc	eax
  2391                              <1> 	;inc	ax
  2392                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2393 000048C4 EBF9                <1> 	jmp 	short alloc_3
  2394                              <1> 		; br 1b
  2395                              <1> alloc_4: ; 1:
  2396                              <1> 	;; pop cx ;; 01/08/2013
  2397                              <1> 		; tst (sp)+ / bump sp
  2398                              <1> 	; 02/04/2013 
  2399 000048C6 E829000000          <1> 	call	free3
  2400                              <1> 		; jsr r0,3f / have found a free block
  2401                              <1> 	; 21/8/2012
  2402 000048CB 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2403 000048CE 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2404                              <1> 		; bic r3,(r2) / set bit for this block 
  2405                              <1> 		            ; / i.e. assign block
  2406                              <1> 		; br 2f
  2407 000048D1 EB09                <1> 	jmp 	short alloc_5
  2408                              <1> 
  2409                              <1> free:
  2410                              <1> 	; 03/02/2022
  2411                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2412                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2413                              <1> 	;
  2414                              <1> 	; calculates byte address and bit position for given block number
  2415                              <1> 	; then sets the corresponding bit in the free storage map
  2416                              <1> 	; 
  2417                              <1> 	; INPUTS ->
  2418                              <1> 	;    r1 - block number for a block structured device
  2419                              <1> 	;    cdev - current device 
  2420                              <1> 	; OUTPUTS ->
  2421                              <1> 	;    free storage map is updated
  2422                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2423                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2424                              <1> 	;
  2425                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2426                              <1>         ;  ((Modified registers: DX, CX))  
  2427                              <1> 
  2428                              <1> 		;mov r2,-(sp) / save r2, r3
  2429                              <1> 		;mov r3,-(sp)
  2430                              <1> 	;push 	ecx
  2431 000048D3 53                  <1> 	push 	ebx ; R2
  2432                              <1> 	;push 	edx ; R3 
  2433                              <1> 
  2434 000048D4 E81B000000          <1>         call    free3
  2435                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2436                              <1> 				 ; / in free storage map for block
  2437 000048D9 660913              <1> 	or 	[ebx], dx  
  2438                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2439                              <1> 			    ;  / indicates free block	
  2440                              <1> 	; 0 -> allocated, 1 -> free
  2441                              <1> 
  2442                              <1> alloc_5:
  2443                              <1> 	; 07/04/2013
  2444                              <1> free_1: ; 2:
  2445                              <1> 	;pop 	edx
  2446                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2447 000048DC 5B                  <1> 	pop	ebx
  2448                              <1> 		; mov (sp)+,r2
  2449                              <1> 	; pop	ecx
  2450 000048DD 803D[AC660000]00    <1> 	cmp 	byte [cdev], 0
  2451                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2452                              <1> 			 ; / cdev = 1, mountable device
  2453 000048E4 7707                <1> 	ja	short alloc_6 ; 1f
  2454                              <1> 		; bne 1f
  2455                              <1> 	;mov	byte [smod], 1
  2456 000048E6 FE05[BD660000]      <1> 	inc 	byte [smod]
  2457                              <1> 		; incb smod / set super block modified for drum
  2458                              <1> 	; eAX (r1) = block number
  2459 000048EC C3                  <1> 	retn
  2460                              <1> 		; rts r0
  2461                              <1> free_2:
  2462                              <1> alloc_6: ; 1:
  2463                              <1> 	;mov 	byte [mmod], 1
  2464 000048ED FE05[BE660000]      <1> 	inc 	byte [mmod]
  2465                              <1> 		; incb	mmod 
  2466                              <1> 		  ; / set super block modified for mountable device
  2467                              <1> 	; eAX (r1) = block number
  2468 000048F3 C3                  <1> 	retn	
  2469                              <1> 		; rts r0
  2470                              <1> free3:
  2471                              <1> 	; 03/02/2022
  2472                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2473                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2474                              <1> 	;
  2475                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2476                              <1> 	; 
  2477                              <1> alloc_free_3: ; 3
  2478                              <1> 	;mov 	dx, 1
  2479                              <1> 	; 03/02/2022
  2480 000048F4 31D2                <1> 	xor	edx, edx
  2481 000048F6 42                  <1> 	inc	edx
  2482                              <1> 	; edx = 1
  2483 000048F7 88C1                <1> 	mov 	cl, al
  2484                              <1> 		; mov r1,r2 / block number, k, = 1		
  2485 000048F9 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2486                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2487 000048FC 7402                <1> 	jz 	short free4
  2488                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2489                              <1> 			       ; / (k) mod 8
  2490                              <1> 	;shl 	dx, cl
  2491                              <1> 	; 03/02/2022
  2492 000048FE D3E2                <1> 	shl	edx, cl
  2493                              <1> free4:
  2494 00004900 0FB7D8              <1> 	movzx 	ebx, ax
  2495                              <1> 		; mov r1,r2 / divide block number by 16
  2496                              <1> 	; 03/02/2022
  2497 00004903 C1EB04              <1> 	shr	ebx, 4
  2498                              <1> 	;shr 	bx, 4
  2499                              <1> 		; asr r2
  2500                              <1> 		; asr r2
  2501                              <1> 		; asr r2
  2502                              <1> 		; asr r2
  2503                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2504                              <1> 		       ; / bit for block is in lower half of word
  2505                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2506                              <1> 		        ; / storage map
  2507                              <1> alloc_free_4: ; 1
  2508                              <1> 	; 03/02/2022
  2509 00004906 D1E3                <1> 	shl	ebx, 1
  2510                              <1> 	;shl 	bx, 1
  2511                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2512 00004908 81C3[82730000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2513                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2514                              <1> 	    		        ; / with block bit in it 	
  2515 0000490E 803D[AC660000]00    <1> 	cmp	byte [cdev], 0
  2516                              <1> 		; tst cdev
  2517 00004915 7606                <1> 	jna	short alloc_free_5
  2518                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2519 00004917 81C308020000        <1> 	add	ebx, mount - systm
  2520                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2521                              <1> 				    ; / mountable device with bit of block to be
  2522                              <1> 				    ; / freed
  2523                              <1> alloc_free_5: ; 1 
  2524 0000491D C3                  <1> 	retn
  2525                              <1> 		; rts r0 / return to 'free'
  2526                              <1> 	      ; 2
  2527                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2528                              <1> 	
  2529                              <1> iget:
  2530                              <1> 	; 03/02/2022
  2531                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2532                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2533                              <1> 	;
  2534                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2535                              <1> 	;
  2536                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2537                              <1> 	; 
  2538                              <1> 	; INPUTS ->
  2539                              <1> 	;    ii - current i-number, rootdir
  2540                              <1> 	;    cdev - new i-node device
  2541                              <1> 	;    idev - current i-node device
  2542                              <1> 	;    imod - current i-node modified flag
  2543                              <1> 	;    mnti - cross device file i-number
  2544                              <1> 	;    r1 - i-numbe rof new i-node
  2545                              <1> 	;    mntd - mountable device number		
  2546                              <1> 	; 	 
  2547                              <1> 	; OUTPUTS ->
  2548                              <1> 	;    cdev, idev, imod, ii, r1
  2549                              <1> 	;
  2550                              <1> 	; ((AX = R1)) input/output
  2551                              <1> 	;
  2552                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2553                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2554                              <1> 
  2555 0000491E 8A15[AC660000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2556 00004924 8A35[AA660000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2557                              <1> 	;
  2558 0000492A 663B05[A8660000]    <1> 	cmp 	ax, [ii]
  2559                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2560 00004931 7504                <1> 	jne 	short iget_1
  2561                              <1> 		; bne 1f
  2562 00004933 38F2                <1> 	cmp	dl, dh
  2563                              <1> 		; cmp idev,cdev
  2564                              <1> 			  ; / is device number of i-node = current device
  2565 00004935 7472                <1>         je      short iget_5
  2566                              <1> 		; beq 2f
  2567                              <1> iget_1: ; 1:
  2568 00004937 30DB                <1> 	xor	bl, bl
  2569 00004939 381D[BC660000]      <1> 	cmp	[imod], bl ; 0	
  2570                              <1> 		; tstb imod / has i-node of current file
  2571                              <1> 			  ; / been modified i.e., imod set
  2572 0000493F 7629                <1> 	jna	short iget_2
  2573                              <1> 		; beq 1f
  2574 00004941 881D[BC660000]      <1> 	mov	[imod], bl ; 0
  2575                              <1> 		;  clrb	imod / if it has, 
  2576                              <1> 			   ; / we must write the new i-node out on disk
  2577                              <1> 	; 03/02/2022
  2578 00004947 50                  <1> 	push	eax ; *
  2579                              <1> 	;push	ax
  2580                              <1> 		; mov r1,-(sp)
  2581                              <1> 	;mov	dl, [cdev]
  2582 00004948 52                  <1> 	push	edx ; **
  2583                              <1> 	;push	dx
  2584                              <1> 		; mov cdev,-(sp)
  2585 00004949 66A1[A8660000]      <1> 	mov	ax, [ii]
  2586                              <1> 		; mov ii,r1
  2587                              <1> 	;mov	dh, [idev]
  2588 0000494F 8835[AC660000]      <1> 	mov	[cdev], dh
  2589                              <1> 		; mov idev,cdev
  2590 00004955 FEC3                <1> 	inc	bl ; 1
  2591                              <1> 	; 31/07/2013
  2592 00004957 881D[44670000]      <1> 	mov     [rw], bl ; 1 == write 
  2593                              <1> 	;;28/07/2013 rw -> u.rw
  2594                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2595 0000495D E848000000          <1> 	call	icalc
  2596                              <1> 		; jsr r0,icalc; 1
  2597                              <1> 	;pop	dx
  2598                              <1> 	; 03/02/2022
  2599 00004962 5A                  <1> 	pop	edx ; **
  2600 00004963 8815[AC660000]      <1> 	mov	[cdev], dl
  2601                              <1> 		; mov (sp)+,cdev
  2602                              <1> 	; 03/02/2022
  2603 00004969 58                  <1> 	pop	eax ; *
  2604                              <1> 	;pop	ax
  2605                              <1> 		; mov (sp)+,r1
  2606                              <1> iget_2: ; 1:
  2607 0000496A 6621C0              <1> 	and	ax, ax
  2608                              <1> 		; tst r1 / is new i-number non zero
  2609 0000496D 7434                <1> 	jz	short iget_4 ; 2f
  2610                              <1> 		; beq 2f / branch if r1=0
  2611                              <1> 
  2612                              <1> 	;mov 	dl, [cdev]
  2613 0000496F 08D2                <1> 	or	dl, dl
  2614                              <1> 		; tst cdev / is the current device number non zero
  2615                              <1> 			 ; / (i.e., device =/ drum)
  2616 00004971 7517                <1> 	jnz	short iget_3 ;  1f
  2617                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2618 00004973 663B05[B2660000]    <1> 	cmp	ax, [mnti]			
  2619                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2620                              <1> 			    ; / file (root directory of mounted device)
  2621 0000497A 750E                <1> 	jne	short iget_3 ; 1f
  2622                              <1> 		; bne 1f
  2623                              <1>         ;mov    bl, [mntd]
  2624 0000497C FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2625 0000497E 8815[AC660000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2626                              <1> 		; mov mntd,cdev / make mounted device the current device
  2627 00004984 66A1[B8660000]      <1> 	mov	ax, [rootdir]
  2628                              <1> 		; mov rootdir,r1
  2629                              <1> iget_3: ; 1:
  2630 0000498A 66A3[A8660000]      <1> 	mov	[ii], ax
  2631                              <1> 		; mov r1,ii
  2632 00004990 8815[AA660000]      <1> 	mov	[idev], dl ; cdev
  2633                              <1> 		; mov cdev,idev
  2634 00004996 30DB                <1> 	xor	bl, bl
  2635                              <1>         ; 31/07/2013
  2636 00004998 881D[44670000]      <1> 	mov     [rw], bl ; 0 == read 
  2637                              <1> 	;;28/07/2013 rw -> u.rw       
  2638                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2639 0000499E E807000000          <1> 	call	icalc
  2640                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2641                              <1> iget_4: ; 2:
  2642 000049A3 66A1[A8660000]      <1> 	mov	ax, [ii]
  2643                              <1> 		; mov ii,r1
  2644                              <1> iget_5:
  2645 000049A9 C3                  <1> 	retn
  2646                              <1> 		; rts r0
  2647                              <1> 
  2648                              <1> icalc:
  2649                              <1> 	; 04/04/2022 (47->31)
  2650                              <1> 	;	(Inode Table/List Address modification)
  2651                              <1> 	; 03/02/2022
  2652                              <1> 	; 02/07/2015
  2653                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2654                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2655                              <1> 	;
  2656                              <1> 	; calculate physical block number from i-number then
  2657                              <1> 	; read or write that block
  2658                              <1> 	;
  2659                              <1> 	; 'icalc' is called from 'iget'
  2660                              <1> 	;
  2661                              <1> 	; for original unix v1:
  2662                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2663                              <1>        	; / (i+31.) mod 16. bytes from its start
  2664                              <1> 	;
  2665                              <1> 	; for retro unix 8086 v1:
  2666                              <1> 	;  i-node is located in block (i+47)/16 and
  2667                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2668                              <1> 	;
  2669                              <1> 	; INPUTS ->
  2670                              <1> 	;    r1 - i-number of i-node
  2671                              <1> 	; 	 
  2672                              <1> 	; OUTPUTS ->
  2673                              <1> 	;    inode r/w
  2674                              <1> 	;
  2675                              <1> 	; ((AX = R1)) input
  2676                              <1> 	;
  2677                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2678                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2679                              <1> 	;
  2680 000049AA 0FB7D0              <1> 	movzx	edx, ax	
  2681                              <1> 	;add	dx, 47
  2682                              <1> 	; 04/04/2022
  2683 000049AD 6683C21F            <1> 	add	dx, 31
  2684 000049B1 89D0                <1> 	mov	eax, edx
  2685                              <1> 	;;add	ax, 47	; add 47 to inode number
  2686                              <1> 	;add	ax, 31
  2687                              <1> 		; add $31.,r1 / add 31. to i-number
  2688 000049B3 50                  <1> 	push	eax
  2689                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2690                              <1> 	; 03/02/2022
  2691 000049B4 C1E804              <1> 	shr	eax, 4
  2692                              <1> 	;shr 	ax, 4
  2693                              <1> 		; asr r1 / divide by 16.
  2694                              <1> 		; asr r1
  2695                              <1> 		; asr r1
  2696                              <1> 		; asr r1 / r1 contains block number of block
  2697                              <1> 		       ; / in which i-node exists
  2698 000049B7 E8330B0000          <1> 	call	dskrd
  2699                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2700                              <1> 	; 31/07/2013
  2701 000049BC 803D[44670000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2702                              <1> 	;; 28/07/2013 rw -> u.rw
  2703                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2704                              <1> 		; tst (r0)
  2705 000049C3 7605                <1> 	jna	short icalc_1
  2706                              <1> 		; beq 1f / branch to wslot when argument
  2707                              <1> 		       ; / in icalc call = 1
  2708                              <1> 	; eAX = r1 = block number
  2709 000049C5 E8970B0000          <1> 	call	wslot
  2710                              <1> 		; jsr r0,wslot / set up data buffer for write
  2711                              <1> 			     ; / (will be same buffer as dskrd got)
  2712                              <1> 	; eBX = r5 points to first word in data area for this block
  2713                              <1> icalc_1: ; 1:
  2714 000049CA 5A                  <1> 	pop	edx 
  2715 000049CB 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2716                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2717                              <1> 			      ; / gives (i+31.) mod 16
  2718 000049CE C1E205              <1> 	shl 	edx, 5
  2719                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2720 000049D1 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2721 000049D3 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2722                              <1>           	; eSI (r5) points to first word in i-node i.	
  2723                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2724                              <1> 			     ; / 32.*(i+31.)mod16
  2725                              <1> 		; mov $5,lsh / for i-node i.
  2726                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2727 000049D5 BF[C4630000]        <1> 	mov	edi, inode
  2728                              <1> 		; mov $inode,r1 / inode is address of first word 
  2729                              <1> 			      ; / of current i-node
  2730                              <1> 	; 03/02/2022
  2731 000049DA 29C9                <1> 	sub	ecx, ecx
  2732 000049DC B108                <1> 	mov	cl, 8 
  2733                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2734                              <1> 		; mov $16.,r3
  2735                              <1>         ; 31/07/2013
  2736 000049DE 382D[44670000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2737                              <1>        ;;28/07/2013 rw -> u.rw                 
  2738                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2739                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2740 000049E4 7609                <1> 	jna	short icalc_3
  2741                              <1> 		; beq 2f / r0 now contains proper return address 
  2742                              <1> 		       ; / for rts r0
  2743                              <1> icalc_2: ; 1:
  2744 000049E6 87F7                <1> 	xchg 	esi, edi
  2745                              <1> 	; overwrite old i-node (in buffer to be written)
  2746 000049E8 F3A5                <1> 	rep 	movsd
  2747                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2748                              <1> 		; dec r3
  2749                              <1> 		; bgt 1b
  2750                              <1> 	;call	dskwr
  2751                              <1> 		; jsr r0,dskwr / write inode out on device
  2752                              <1> 	;retn
  2753                              <1> 		; rts r0
  2754                              <1> 	; 03/02/2022
  2755 000049EA E98E0B0000          <1> 	jmp	dskwr
  2756                              <1> icalc_3: ; 2:
  2757                              <1> 	; copy new i-node into inode area of (core) memory
  2758 000049EF F3A5                <1> 	rep 	movsd
  2759                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2760                              <1> 		                ; / "inode" area of core
  2761                              <1> 		; dec r3
  2762                              <1> 		; bgt 2b
  2763 000049F1 C3                  <1> 	retn
  2764                              <1> 		; rts r0
  2765                              <1> 
  2766                              <1> access:
  2767                              <1> 	; 03/02/2022
  2768                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2769                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2770                              <1> 	;
  2771                              <1> 	; check whether user is owner of file or user has read or write
  2772                              <1> 	; permission (based on i.flgs).
  2773                              <1> 	;
  2774                              <1> 	; INPUTS ->
  2775                              <1> 	;    r1 - i-number of file
  2776                              <1> 	;    u.uid
  2777                              <1> 	; arg0 -> (owner flag mask)	 		
  2778                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2779                              <1> 	; OUTPUTS ->
  2780                              <1> 	;    inode (or jump to error)
  2781                              <1> 	;
  2782                              <1> 	; ((AX = R1)) input/output
  2783                              <1> 	;
  2784                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2785                              <1> 	;
  2786                              <1> 
  2787                              <1> 	;push	dx  ; save flags (DL)
  2788                              <1> 	; 03/02/2022
  2789 000049F2 52                  <1> 	push	edx ; save flags (DL)
  2790 000049F3 E826FFFFFF          <1> 	call	iget
  2791                              <1> 		; jsr r0,iget / read in i-node for current directory
  2792                              <1> 			    ; / (i-number passed in r1)
  2793 000049F8 8A0D[C4630000]      <1> 	mov	cl, [i.flgs]
  2794                              <1> 		; mov i.flgs,r2
  2795                              <1> 	; 03/02/2022
  2796 000049FE 5A                  <1> 	pop	edx ; restore flags (DL)
  2797                              <1> 	;pop	dx  ; restore flags (DL)
  2798 000049FF 8A35[0E670000]      <1> 	mov	dh, [u.uid]
  2799 00004A05 3A35[C7630000]      <1> 	cmp	dh, [i.uid]
  2800                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2801 00004A0B 7503                <1> 	jne	short access_1
  2802                              <1> 		; bne 1f / no, then branch
  2803 00004A0D C0E902              <1> 	shr	cl, 2
  2804                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2805                              <1> 		        ; / read/write bits
  2806                              <1> 		; asrb r2
  2807                              <1> access_1: ; 1:
  2808 00004A10 20D1                <1> 	and	cl, dl
  2809                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2810                              <1> 			     ; / in access call
  2811 00004A12 7513                <1> 	jnz	short access_2
  2812                              <1> 		; bne 1f
  2813 00004A14 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2814                              <1> 		; tstb u.uid
  2815 00004A16 740F                <1> 	jz	short access_2 ; yes, super user
  2816                              <1> 	;jnz	error
  2817                              <1> 		; beq 1f
  2818                              <1> 		; jmp error
  2819 00004A18 C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2819 00004A20 0000                <1>
  2820                              <1> 			; 'permission denied !' error
  2821 00004A22 E9E1E7FFFF          <1> 	jmp	error
  2822                              <1> 
  2823                              <1> access_2: ; 1:
  2824                              <1> 	; DL = flags
  2825 00004A27 C3                  <1> 	retn
  2826                              <1> 		; rts r0
  2827                              <1> 
  2828                              <1> setimod:
  2829                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2830                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2831                              <1> 	;
  2832                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2833                              <1> 	; the inode has been modified. Also puts the time of modification
  2834                              <1> 	; into the inode.
  2835                              <1> 	;
  2836                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2837                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2838                              <1> 	;
  2839                              <1> 	
  2840                              <1> 	; push 	edx
  2841 00004A28 50                  <1> 	push	eax
  2842                              <1> 
  2843 00004A29 C605[BC660000]01    <1> 	mov 	byte [imod], 1
  2844                              <1> 		; movb $1,imod / set current i-node modified bytes
  2845                              <1> 	; Erdogan Tan 14-7-2012
  2846 00004A30 E821E3FFFF          <1> 	call 	epoch
  2847                              <1> 		 ; mov s.time,i.mtim 
  2848                              <1> 			    ; / put present time into file modified time
  2849                              <1> 		 ; mov s.time+2,i.mtim+2
  2850                              <1> 
  2851 00004A35 A3[DE630000]        <1> 	mov 	[i.mtim], eax
  2852                              <1> 	
  2853                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2854                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2855 00004A3A 833D[DA630000]00    <1> 	cmp	dword [i.ctim], 0
  2856 00004A41 7505                <1> 	jnz	short setimod_ok
  2857                              <1> 
  2858 00004A43 A3[DA630000]        <1> 	mov 	[i.ctim], eax
  2859                              <1> 
  2860                              <1> setimod_ok: ; 31/07/2013
  2861 00004A48 58                  <1> 	pop	eax
  2862                              <1> 	;pop	edx
  2863                              <1> 	
  2864 00004A49 C3                  <1> 	retn
  2865                              <1> 		; rts r0
  2866                              <1> 
  2867                              <1> itrunc:
  2868                              <1> 	; 03/02/2022
  2869                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2870                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2871                              <1> 	;
  2872                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2873                              <1> 	;  to zero length.
  2874                              <1> 	;
  2875                              <1> 	; INPUTS ->
  2876                              <1> 	;    r1 - i-number of i-node
  2877                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2878                              <1> 	;    i.flgs - large file flag		
  2879                              <1> 	;    i.size - size of file	
  2880                              <1> 	; 	 
  2881                              <1> 	; OUTPUTS ->
  2882                              <1> 	;    i.flgs - large file flag is cleared
  2883                              <1> 	;    i.size - set to 0	
  2884                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2885                              <1> 	;    setimod - set to indicate i-node has been modified
  2886                              <1> 	;    r1 - i-number of i-node  					
  2887                              <1> 	;
  2888                              <1> 	; ((AX = R1)) input/output
  2889                              <1> 	;
  2890                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2891                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2892                              <1> 
  2893 00004A4A E8CFFEFFFF          <1> 	call	iget
  2894                              <1> 		; jsr r0,iget
  2895 00004A4F BE[CA630000]        <1> 	mov	esi, i.dskp
  2896                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2897 00004A54 31C0                <1> 	xor	eax, eax
  2898                              <1> itrunc_1: ; 1:
  2899 00004A56 66AD                <1> 	lodsw
  2900                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2901                              <1> 	; 03/02/2022
  2902 00004A58 09C0                <1> 	or	eax, eax
  2903                              <1> 	;or 	ax, ax
  2904 00004A5A 7433                <1> 	jz	short itrunc_5
  2905                              <1> 		; beq 5f
  2906 00004A5C 56                  <1> 	push	esi
  2907                              <1> 		; mov r2,-(sp)
  2908                              <1> 	; 03/02/2022
  2909 00004A5D F605[C5630000]10    <1> 	test	byte [i.flgs+1], 10h
  2910                              <1> 	;test	word [i.flgs], 1000h
  2911                              <1> 		; bit $10000,i.flgs / test large file bit?
  2912 00004A64 7423                <1> 	jz	short itrunc_4
  2913                              <1> 		; beq 4f / if clear, branch
  2914 00004A66 50                  <1> 	push	eax
  2915                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2916 00004A67 E8830A0000          <1> 	call	dskrd
  2917                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2918                              <1> 			     ; / pointed to by r5
  2919                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2920                              <1> 	; 03/02/2022
  2921 00004A6C 31C9                <1> 	xor	ecx, ecx
  2922 00004A6E FEC5                <1> 	inc	ch ; mov ch, 1
  2923                              <1> 	; ecx = 256
  2924                              <1> 	;mov	ecx, 256
  2925                              <1> 		; mov $256.,r3 / move word count into r3
  2926 00004A70 89DE                <1> 	mov	esi, ebx
  2927                              <1> itrunc_2: ; 2:
  2928 00004A72 66AD                <1> 	lodsw
  2929                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2930                              <1> 			     ; / physical block number
  2931                              <1> 	; 03/02/2022
  2932 00004A74 21C0                <1> 	and	eax, eax
  2933                              <1> 	;and	ax, ax
  2934 00004A76 7407                <1> 	jz	short itrunc_3
  2935                              <1> 		; beq 3f / branch if zero
  2936                              <1> 	; 03/02/2022
  2937 00004A78 51                  <1> 	push	ecx
  2938                              <1> 	;push	cx
  2939                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2940                              <1> 	;push	esi
  2941                              <1> 		; mov r5,-(sp)
  2942 00004A79 E855FEFFFF          <1> 	call	free
  2943                              <1> 		; jsr r0,free / free block in free storage map
  2944                              <1> 	;pop	esi
  2945                              <1> 		; mov(sp)+,r5
  2946                              <1> 	;pop	cx
  2947 00004A7E 59                  <1> 	pop	ecx
  2948                              <1> 		; mov (sp)+,r3
  2949                              <1> itrunc_3: ; 3:
  2950 00004A7F E2F1                <1> 	loop	itrunc_2
  2951                              <1> 		; dec r3 / decrement word count
  2952                              <1> 		; bgt 2b / branch if positive
  2953 00004A81 58                  <1> 	pop	eax
  2954                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2955                              <1> 			     ; / indirect block
  2956                              <1> 	; 01/08/2013
  2957                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2958                              <1> 	; 03/02/2022
  2959 00004A82 8025[C5630000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2960                              <1> itrunc_4: ; 4:
  2961 00004A89 E845FEFFFF          <1> 	call	free
  2962                              <1> 		; jsr r0,free / free indirect block
  2963 00004A8E 5E                  <1> 	pop	esi
  2964                              <1> 		; mov (sp)+,r2
  2965                              <1> itrunc_5: ; 5:
  2966 00004A8F 81FE[DA630000]      <1> 	cmp	esi, i.dskp+16
  2967                              <1> 		; cmp r2,$i.dskp+16.
  2968 00004A95 72BF                <1> 	jb	short itrunc_1	
  2969                              <1> 		; bne 1b / branch until all i.dskp entries check
  2970                              <1> 	; 03/02/2022
  2971                              <1> 	;and	byte [i.flgs+1], 0EFh
  2972                              <1> 	; 01/08/2013
  2973                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2974                              <1> 		; bic $10000,i.flgs / clear large file bit
  2975 00004A97 BF[CA630000]        <1> 	mov	edi, i.dskp
  2976                              <1> 	;mov	cx, 8
  2977                              <1> 	;xor 	ax, ax
  2978                              <1> 	; 03/02/2022
  2979 00004A9C 29C9                <1> 	sub	ecx, ecx
  2980 00004A9E B108                <1> 	mov	cl, 8
  2981 00004AA0 29C0                <1> 	sub	eax, eax
  2982 00004AA2 66A3[C8630000]      <1> 	mov	[i.size], ax ; 0
  2983                              <1> 		; clr i.size / zero file size
  2984 00004AA8 F366AB              <1> 	rep	stosw
  2985                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2986                              <1> 			   ; / zero block pointers
  2987 00004AAB E878FFFFFF          <1> 	call	setimod
  2988                              <1> 		; jsr r0,setimod / set i-node modified flag
  2989 00004AB0 66A1[A8660000]      <1> 	mov	ax, [ii]
  2990                              <1> 		; mov ii,r1
  2991 00004AB6 C3                  <1> 	retn
  2992                              <1> 		; rts r0
  2993                              <1> 
  2994                              <1> imap:
  2995                              <1> 	; 12/02/2022
  2996                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2997                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2998                              <1> 	;
  2999                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3000                              <1> 	; allocation bit for an i-node whose number in r1.
  3001                              <1> 	;
  3002                              <1> 	; INPUTS ->
  3003                              <1> 	;    r1 - contains an i-number
  3004                              <1> 	;    fsp - start of table containing open files
  3005                              <1> 	;
  3006                              <1> 	; OUTPUTS ->
  3007                              <1> 	;    r2 - byte address of byte with the allocation bit
  3008                              <1> 	;    mq - a mask to locate the bit position.	
  3009                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3010                              <1> 	;
  3011                              <1> 	; ((AX = R1)) input/output
  3012                              <1> 	; ((DL/DX = MQ)) output
  3013                              <1> 	; ((BX = R2)) output
  3014                              <1> 	;
  3015                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3016                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3017                              <1> 	;
  3018                              <1> 		; / get the byte that has the allocation bit for 
  3019                              <1> 		; / the i-number contained in r1
  3020                              <1> 	;mov	dx, 1
  3021 00004AB7 B201                <1> 	mov	dl, 1
  3022                              <1> 		; mov $1,mq / put 1 in the mq
  3023 00004AB9 0FB7D8              <1> 	movzx	ebx, ax
  3024                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3025                              <1>  		          ; / in the map we must find
  3026 00004ABC 6683EB29            <1> 	sub	bx, 41
  3027                              <1> 		; sub $41.,r2 / r2 has i-41
  3028 00004AC0 88D9                <1> 	mov	cl, bl
  3029                              <1> 		; mov r2,r3 / r3 has i-41
  3030 00004AC2 80E107              <1> 	and	cl, 7
  3031                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3032                              <1> 			   ; / the bit position
  3033 00004AC5 7402                <1> 	jz	short imap1
  3034                              <1> 	;shl	dx, cl
  3035 00004AC7 D2E2                <1> 	shl	dl, cl
  3036                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3037                              <1> imap1:			   ; / to the left to mask the correct bit
  3038                              <1> 	; 03/02/2022
  3039 00004AC9 C1EB03              <1> 	shr	ebx, 3
  3040                              <1> 	;shr	bx, 3
  3041                              <1> 		; asr r2
  3042                              <1> 		; asr r2
  3043                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3044                              <1> 		       ; / from the start of the map
  3045                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3046 00004ACC BE[80730000]        <1> 	mov	esi, systm
  3047                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3048                              <1> 				; / the super block for drum
  3049                              <1> 	;cmp	word [cdev], 0
  3050 00004AD1 803D[AC660000]00    <1> 	cmp	byte [cdev], 0
  3051                              <1> 		; tst cdev / is the device the disk
  3052 00004AD8 7606                <1> 	jna	short imap2
  3053                              <1> 		; beq 1f / yes
  3054 00004ADA 81C608020000        <1> 	add	esi, mount - systm
  3055                              <1> 		; add $mount-systm,r2 / for mounted device,
  3056                              <1> 			; / r2 points to 1st word of its super block
  3057                              <1> imap2: ; 1:
  3058 00004AE0 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3059                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3060 00004AE3 6683C304            <1> 	add	bx, 4
  3061 00004AE7 01F3                <1> 	add	ebx, esi
  3062                              <1>         	; add (sp)+,r2 / ?
  3063                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3064                              <1> 		      ;; (2 + free map size + 2)
  3065                              <1> 		; add $2,r2 / ?
  3066                              <1>  	
  3067                              <1> 	; 12/02/2022
  3068 00004AE9 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3069 00004AEF 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3070                              <1> 			  ; if inode num overs inode count
  3071                              <1> 
  3072                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3073                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3074                              <1> 
  3075                              <1> 	; 11/02/2022
  3076                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3077                              <1> 	;	(number of requested inode > inode count)
  3078                              <1> 
  3079 00004AF1 C3                  <1> 	retn
  3080                              <1> 		; rts r0
  2054                                  %include 'u6.s'        ; 31/05/2015
  2055                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS6.INC
  2056                              <1> ; Last Modification: 13/06/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 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2067                              <1> ;
  2068                              <1> ; ****************************************************************************
  2069                              <1> ; 18/11/2015
  2070                              <1> 
  2071                              <1> readi:
  2072                              <1> 	; 03/02/2022
  2073                              <1> 	; 20/05/2015
  2074                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2075                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2076                              <1> 	;
  2077                              <1> 	; Reads from an inode whose number in R1
  2078                              <1> 	; 
  2079                              <1> 	; INPUTS ->
  2080                              <1> 	;    r1 - inode number
  2081                              <1> 	;    u.count - byte count user desires
  2082                              <1> 	;    u.base - points to user buffer
  2083                              <1> 	;    u.fofp - points to word with current file offset
  2084                              <1> 	; OUTPUTS ->
  2085                              <1> 	;    u.count - cleared
  2086                              <1> 	;    u.nread - accumulates total bytes passed back
  2087                              <1> 	;
  2088                              <1> 	; ((AX = R1)) input/output
  2089                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2090                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2091                              <1> 
  2092 00004AF2 31D2                <1> 	xor	edx, edx ; 0
  2093 00004AF4 8915[F0660000]      <1> 	mov 	[u.nread], edx ; 0
  2094                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2095 00004AFA 668915[27670000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2096 00004B01 3915[EC660000]      <1> 	cmp 	[u.count], edx ; 0
  2097                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2098 00004B07 7701                <1> 	ja 	short readi_1 ; 1f
  2099                              <1> 		 ; bgt 1f / yes, branch
  2100 00004B09 C3                  <1> 	retn
  2101                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2102                              <1> readi_1: ; 1:
  2103                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2104 00004B0A 6683F828            <1> 	cmp	ax, 40
  2105                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2106                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2107                              <1>         ;ja	dskr 
  2108                              <1> 		 ; ble 1f / yes, branch
  2109                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2110                              <1> 		 ;         / read file with i-node number (r1)
  2111                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2112                              <1> 	; 03/02/2022
  2113 00004B0E 7605                <1> 	jna	short readi_3
  2114 00004B10 E9CF000000          <1> 	jmp	dskr
  2115                              <1> readi_3:
  2116                              <1> 	; (20/05/2015)
  2117 00004B15 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2118                              <1> 	; 1:
  2119 00004B16 0FB6D8              <1> 	movzx	ebx, al
  2120                              <1> 	; 03/02/2022
  2121 00004B19 C1E302              <1> 	shl	ebx, 2
  2122                              <1> 	;shl	bx, 2
  2123                              <1> 		 ; asl r1 / multiply inode number by 2
  2124 00004B1C 81C3[204B0000]      <1> 	add	ebx, readi_2 - 4
  2125 00004B22 FF23                <1> 	jmp	dword [ebx]	
  2126                              <1> 		 ; jmp *1f-2(r1)
  2127                              <1> readi_2: ; 1:
  2128 00004B24 [704B0000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2129                              <1> 		 ;rtty / tty; r1=2
  2130                              <1> 		 ;rppt / ppt; r1=4
  2131 00004B28 [C04B0000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2132                              <1> 		 ;rmem / mem; r1=6
  2133                              <1> 		 ;rrf0 / rf0
  2134                              <1> 		 ;rrk0 / rk0
  2135                              <1> 		 ;rtap / tap0
  2136                              <1> 		 ;rtap / tap1
  2137                              <1> 		 ;rtap / tap2
  2138                              <1> 		 ;rtap / tap3
  2139                              <1> 		 ;rtap / tap4
  2140                              <1> 		 ;rtap / tap5
  2141                              <1> 		 ;rtap / tap6
  2142                              <1> 		 ;rtap / tap7
  2143 00004B2C [A0530000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2144 00004B30 [A0530000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2145 00004B34 [A0530000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2146 00004B38 [A0530000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2147 00004B3C [A0530000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2148 00004B40 [A0530000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2149 00004B44 [D54B0000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2150 00004B48 [BC4B0000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2151                              <1> 		 ;rcvt / tty0
  2152 00004B4C [BC4B0000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2153                              <1> 		 ;rcvt / tty1
  2154 00004B50 [BC4B0000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2155                              <1> 		 ;rcvt / tty2
  2156 00004B54 [BC4B0000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2157                              <1> 		 ;rcvt / tty3
  2158 00004B58 [BC4B0000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2159                              <1> 		 ;rcvt / tty4
  2160 00004B5C [BC4B0000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2161                              <1> 		 ;rcvt / tty5
  2162 00004B60 [BC4B0000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2163                              <1> 		 ;rcvt / tty6
  2164 00004B64 [BC4B0000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2165                              <1> 		 ;rcvt / tty7
  2166 00004B68 [BC4B0000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2167                              <1> 		 ;rcrd / crd
  2168 00004B6C [BC4B0000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2169                              <1> 
  2170                              <1> rtty: ; / read from console tty
  2171                              <1> 	; 03/02/2022
  2172                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2173                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2174                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2175                              <1> 	;	     must be written immediate on video page (screen)
  2176                              <1> 	;	     when it is required.	
  2177                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2178                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2179                              <1> 	;
  2180                              <1> 	; Console tty buffer is PC keyboard buffer
  2181                              <1> 	; and keyboard-keystroke handling is different than original
  2182                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2183                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2184                              <1> 	;
  2185                              <1> 	; 06/12/2013
  2186 00004B70 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2187 00004B77 8A83[23640000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2188                              <1> rttys:
  2189                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2190                              <1> 	               ; / of the control and status block
  2191                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2192                              <1> 		       ; / tty buffer
  2193                              <1> 	; 28/07/2013
  2194 00004B7D A2[16670000]        <1> 	mov 	[u.ttyn], al
  2195                              <1> 	; 13/01/2014
  2196 00004B82 FEC0                <1> 	inc	al
  2197 00004B84 A2[F8660000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2198                              <1> rtty_nc: ; 01/02/2014
  2199                              <1> 	; 29/09/2013
  2200                              <1> 	;mov	ecx, 10
  2201                              <1> 	; 03/02/2022
  2202 00004B89 29C9                <1> 	sub	ecx, ecx
  2203 00004B8B B10A                <1> 	mov	cl, 10
  2204                              <1> rtty_1: 	; 01/02/2014
  2205                              <1> 	;push 	cx ; 29/09/2013
  2206                              <1> 	; 03/02/2022
  2207 00004B8D 51                  <1> 	push	ecx
  2208                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2209 00004B8E B001                <1> 	mov 	al, 1
  2210 00004B90 E8C40B0000          <1> 	call 	getc
  2211                              <1> 	; 03/02/2022
  2212 00004B95 59                  <1> 	pop	ecx
  2213                              <1> 	;pop 	cx ; 29/09/2013	
  2214 00004B96 7516                <1> 	jnz	short rtty_2
  2215                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2216                              <1> 	               ; / of chars. Is this number non-zero?
  2217 00004B98 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2218                              <1> 	; 05/10/2013
  2219 00004B9A 8A25[16670000]      <1> 	mov	ah, [u.ttyn]
  2220                              <1> 	; 29/09/2013
  2221 00004BA0 E898FBFFFF          <1> 	call	sleep
  2222                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2223                              <1>                 ;           / (120 chars.)
  2224                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2225 00004BA5 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2226                              <1> 
  2227                              <1> rtty_idle:
  2228                              <1> 	; 29/07/2013
  2229 00004BA7 E804FBFFFF          <1> 	call 	idle
  2230 00004BAC EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2231                              <1> 	;1:
  2232                              <1> 		; tst 2(r5) / is the number of characters zero
  2233                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2234                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2235                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2236                              <1> 		          ; / contains the next char.
  2237                              <1> 		; dec 2(r5) / decrement the character count
  2238                              <1> rtty_2:
  2239 00004BAE 30C0                <1> 	xor 	al, al
  2240 00004BB0 E8A40B0000          <1> 	call 	getc
  2241 00004BB5 E892000000          <1> 	call	passc
  2242                              <1> 		; jsr r0,passc / move the character to core (user)
  2243                              <1> 	;; 17/10/2015 - 16/07/2015
  2244                              <1> 	; 19/06/2014
  2245                              <1> 	;;jnz	short rtty_nc
  2246 00004BBA 58                  <1> 	pop	eax  ; (20/05/2015)
  2247 00004BBB C3                  <1> 	retn 
  2248                              <1> ;ret1:
  2249                              <1> 		; jmp ret / return to caller via 'ret'
  2250                              <1> 
  2251                              <1> rcvt:   ; < receive/read character from tty >
  2252                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2253                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2254                              <1> 	;
  2255                              <1> 	; Retro UNIX 8086 v1 modification !
  2256                              <1> 	; 
  2257                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2258                              <1> 	;		(exactly different than this one)
  2259                              <1> 	;	was in 'u9.s' file.
  2260                              <1> 	;
  2261 00004BBC 2C0A                <1> 	sub 	al, 10
  2262                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2263                              <1> 	; 16/07/2013
  2264                              <1> 	; 21/05/2013
  2265 00004BBE EBBD                <1>         jmp     short rttys
  2266                              <1>       
  2267                              <1> ;rppt: / read paper tape
  2268                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2269                              <1> ;			 / places
  2270                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2271                              <1> ;		       / also enables read bit in prs
  2272                              <1> ;	jsr	r0,passc / place character in users buffer area
  2273                              <1> ;	br	rppt
  2274                              <1> 
  2275                              <1> rmem: ; / transfer characters from memory to a user area of core
  2276                              <1> 	; 17/10/2015
  2277                              <1> 	; 11/06/2015
  2278                              <1> 	; 24/05/2015
  2279                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2280                              <1> 	;
  2281 00004BC0 8B35[D8660000]      <1> 	mov     esi, [u.fofp]
  2282                              <1> rmem_1:
  2283 00004BC6 8B1E                <1>         mov     ebx, [esi]        
  2284                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2285                              <1> 		               ; / to be transferred to user
  2286 00004BC8 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2287                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2288                              <1> 			    ; / char in memory file
  2289 00004BCA 8A03                <1> 	mov	al, [ebx]
  2290                              <1> 		; movb (r1),r1 / get character from memory file, 
  2291                              <1> 		             ; / put it in r1
  2292 00004BCC E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2293                              <1> 			     ;  / the next byte of the users core area
  2294                              <1> 		; br rmem / continue
  2295 00004BD1 75F3                <1> 	jnz	short rmem_1
  2296                              <1> ret_:
  2297 00004BD3 58                  <1> 	pop	eax ; 09/06/2015
  2298 00004BD4 C3                  <1> 	retn
  2299                              <1> 
  2300                              <1> rlpr:
  2301                              <1> ;1:
  2302                              <1> ;rcrd:
  2303 00004BD5 C705[17670000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2303 00004BDD 0000                <1>
  2304 00004BDF E924E6FFFF          <1> 	jmp	error
  2305                              <1> 		;jmp	error / see 'error' routine
  2306                              <1> 
  2307                              <1> dskr:
  2308                              <1> 	; 12/10/2015
  2309                              <1> 	; 21/08/2015
  2310                              <1> 	; 25/07/2015
  2311                              <1> 	; 10/07/2015
  2312                              <1> 	; 16/06/2015
  2313                              <1> 	; 31/05/2015
  2314                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2315                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2316                              <1> dskr_0:
  2317 00004BE4 50                  <1> 	push	eax
  2318                              <1> 		; mov (sp),r1 / i-number in r1
  2319                              <1> 	; AX = i-number
  2320 00004BE5 E834FDFFFF          <1> 	call	iget
  2321                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2322 00004BEA 0FB715[C8630000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2323                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2324 00004BF1 8B1D[D8660000]      <1> 	mov	ebx, [u.fofp]
  2325 00004BF7 2B13                <1> 	sub	edx, [ebx]
  2326                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2327                              <1>         ; 12/10/2015
  2328                              <1> 	; jna     short ret_ 
  2329                              <1> 		; blos ret
  2330 00004BF9 7709                <1> 	ja	short dskr_1
  2331                              <1> 	;
  2332                              <1> dskr_retn: ; 12/10/2015
  2333 00004BFB 58                  <1> 	pop	eax
  2334 00004BFC C605[29670000]00    <1> 	mov	byte [u.kcall], 0
  2335 00004C03 C3                  <1> 	retn	
  2336                              <1> dskr_1: 
  2337 00004C04 3B15[EC660000]      <1> 	cmp     edx, [u.count] 
  2338                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2339                              <1> 			       ; / to carry out read
  2340 00004C0A 7306                <1> 	jnb	short dskr_2
  2341                              <1> 		; bhis 1f
  2342 00004C0C 8915[EC660000]      <1> 	mov	[u.count], edx
  2343                              <1> 		; mov r2,u.count / no, just read to end of file
  2344                              <1> dskr_2: ; 1:
  2345                              <1> 	; AX = i-number
  2346 00004C12 E89EFBFFFF          <1> 	call	mget
  2347                              <1> 		; jsr r0,mget / returns physical block number of block 
  2348                              <1> 			    ; / in file where offset points
  2349                              <1> 	; eAX = physical block number
  2350 00004C17 E8D3080000          <1> 	call	dskrd
  2351                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2352                              <1> 			     ; / 1st word of data in buffer
  2353                              <1> 	; 09/06/2015
  2354 00004C1C 803D[29670000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2355 00004C23 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2356 00004C25 66833D[27670000]00  <1> 	cmp	word [u.pcount], 0
  2357 00004C2D 7705                <1> 	ja	short dskr_4
  2358                              <1> dskr_3:
  2359                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2360 00004C2F E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2361                              <1> dskr_4:
  2362                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2363 00004C34 E831030000          <1> 	call	sioreg
  2364                              <1> 		; jsr r0,sioreg
  2365 00004C39 87F7                <1> 	xchg	esi, edi
  2366                              <1> 	; eDI = file (user data) offset
  2367                              <1> 	; eSI = sector (I/O) buffer offset
  2368                              <1> 	; eCX = byte count
  2369 00004C3B F3A4                <1> 	rep	movsb
  2370                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2371                              <1> 		                 ; / starting at u.base
  2372                              <1> 		; dec r3
  2373                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2374                              <1> 	; 25/07/2015
  2375                              <1> 	; eax = remain bytes in buffer
  2376                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2377 00004C3D 09C0                <1> 	or	eax, eax
  2378 00004C3F 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2379                              <1> 	; 03/08/2013
  2380                              <1> 	;pop	eax
  2381 00004C41 390D[EC660000]      <1> 	cmp	[u.count], ecx ; 0
  2382                              <1> 		; tst u.count / all bytes read off disk
  2383                              <1> 		; bne dskr
  2384                              <1> 		; br ret
  2385                              <1>         ;ja      short dskr_0
  2386                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2387                              <1> 	;retn
  2388                              <1> 	; 12/10/2015
  2389 00004C47 76B2                <1> 	jna	short dskr_retn
  2390 00004C49 58                  <1> 	pop	eax  ; (i-node number)
  2391 00004C4A EB98                <1> 	jmp	short dskr_0
  2392                              <1> 	
  2393                              <1> passc:
  2394                              <1> 	; 18/10/2015
  2395                              <1> 	; 10/07/2015
  2396                              <1> 	; 01/07/2015
  2397                              <1> 	; 08/06/2015
  2398                              <1> 	; 04/06/2015
  2399                              <1> 	; 20/05/2015
  2400                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2401                              <1> 	;
  2402                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2403                              <1> 	;		      to physical address
  2404 00004C4C 66833D[27670000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2405                              <1> 			     ; 1-4095 --> use previous physical base address
  2406                              <1> 			     ; in [u.pbase]
  2407 00004C54 7705                <1> 	ja	short passc_3
  2408                              <1> 	; 08/06/2015 - 10/07/2015
  2409 00004C56 E82C000000          <1> 	call	trans_addr_w
  2410                              <1> passc_3:
  2411                              <1> 	; 19/05/2015
  2412 00004C5B 66FF0D[27670000]    <1> 	dec	word [u.pcount]
  2413                              <1> 	;
  2414 00004C62 8B1D[23670000]      <1> 	mov	ebx, [u.pbase]
  2415 00004C68 8803                <1> 	mov	[ebx], al
  2416                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2417                              <1> 		               ; / users buffer
  2418 00004C6A FF05[E8660000]      <1> 	inc	dword [u.base]
  2419                              <1> 		; inc u.base / increment the pointer to point to 
  2420                              <1> 			  ; / the next byte in users buffer
  2421 00004C70 FF05[23670000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2422 00004C76 FF05[F0660000]      <1> 	inc	dword [u.nread]
  2423                              <1> 		; inc u.nread / increment the number of bytes read
  2424 00004C7C FF0D[EC660000]      <1> 	dec	dword [u.count]
  2425                              <1> 		; dec u.count / decrement the number of bytes to be read
  2426                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2427 00004C82 C3                  <1> 	retn
  2428                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2429                              <1> 		             ; / 'readi' by:
  2430                              <1> 		;/ (1) pop the return address off the stack into r0
  2431                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2432                              <1> 	;1:
  2433                              <1> 		; clr	*$ps / clear processor status
  2434                              <1> 		; rts r0 / return to address currently on top of stack
  2435                              <1> 
  2436                              <1> trans_addr_r:
  2437                              <1> 	; Translate virtual address to physical address 
  2438                              <1> 	; for reading from user's memory space
  2439                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2440                              <1> 	; 18/10/2015
  2441                              <1> 	; 10/07/2015
  2442                              <1> 	; 09/06/2015
  2443                              <1> 	; 08/06/2015 
  2444                              <1> 	; 04/06/2015
  2445                              <1> 	;
  2446                              <1> 	; 18/10/2015
  2447 00004C83 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2448 00004C85 EB04                <1> 	jmp 	short trans_addr_rw
  2449                              <1> 
  2450                              <1> 	;push	eax
  2451                              <1> 	;push	ebx
  2452                              <1> 	;mov	ebx, [u.base]
  2453                              <1> 	;call	get_physical_addr ; get physical address
  2454                              <1> 	;;jnc	short cpass_0
  2455                              <1> 	;jnc	short passc_1
  2456                              <1> 	;mov	[u.error], eax
  2457                              <1> 	;;pop	ebx
  2458                              <1> 	;;pop	eax
  2459                              <1> 	;jmp	error
  2460                              <1> ;cpass_0:
  2461                              <1> 	; 18/10/2015
  2462                              <1> 	; 20/05/2015
  2463                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2464                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2465                              <1> 	;pop	ebx
  2466                              <1> 	;pop	eax
  2467                              <1> 	;retn	; 08/06/2015
  2468                              <1> 
  2469                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2470                              <1> trans_addr_w:
  2471                              <1> 	; Translate virtual address to physical address 
  2472                              <1> 	; for writing to user's memory space
  2473                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2474                              <1> 	; 18/10/2015
  2475                              <1> 	; 29/07/2015
  2476                              <1> 	; 10/07/2015
  2477                              <1> 	; 09/06/2015
  2478                              <1> 	; 08/06/2015
  2479                              <1> 	; 04/06/2015 (passc)
  2480                              <1> 	;
  2481                              <1> 	; 18/10/2015
  2482 00004C87 29D2                <1> 	sub	edx, edx
  2483 00004C89 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2484                              <1> trans_addr_rw:
  2485 00004C8B 50                  <1> 	push	eax
  2486 00004C8C 53                  <1> 	push	ebx
  2487                              <1> 	; 18/10/2015
  2488 00004C8D 52                  <1> 	push 	edx ; r/w sign (in DL)
  2489                              <1> 	;
  2490 00004C8E 8B1D[E8660000]      <1> 	mov	ebx, [u.base]
  2491 00004C94 E854DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2492 00004C99 730A                <1> 	jnc	short passc_0
  2493 00004C9B A3[17670000]        <1> 	mov	[u.error], eax
  2494                              <1> 	;pop	edx
  2495                              <1> 	;pop 	ebx
  2496                              <1> 	;pop	eax
  2497 00004CA0 E963E5FFFF          <1> 	jmp	error
  2498                              <1> passc_0:
  2499 00004CA5 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2500 00004CA8 5A                  <1> 	pop	edx ; 18/10/2015
  2501 00004CA9 7517                <1> 	jnz	short passc_1
  2502                              <1> 	; 18/10/2015
  2503 00004CAB 20D2                <1> 	and 	dl, dl
  2504 00004CAD 7413                <1> 	jz	short passc_1
  2505                              <1> 	; 20/05/2015
  2506                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2507                              <1> 	; EBX = linear address
  2508 00004CAF 51                  <1> 	push 	ecx
  2509 00004CB0 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2510 00004CB1 E8A6DBFFFF          <1> 	call 	copy_page
  2511 00004CB6 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2512 00004CB7 59                  <1> 	pop	ecx
  2513 00004CB8 7217                <1> 	jc	short passc_2
  2514                              <1> 	; 03/02/2022
  2515                              <1> 	;push	eax ; physical address of the new/allocated page
  2516                              <1> 	;call	add_to_swap_queue
  2517                              <1> 	;pop	eax
  2518                              <1> 	; 18/10/2015
  2519 00004CBA 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2520                              <1> 	;mov 	ecx, PAGE_SIZE
  2521                              <1> 	;sub	ecx, ebx 
  2522 00004CC0 01D8                <1> 	add	eax, ebx  
  2523                              <1> passc_1: 
  2524                              <1> 	; 18/10/2015
  2525                              <1> 	; 20/05/2015
  2526 00004CC2 A3[23670000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2527 00004CC7 66890D[27670000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2528 00004CCE 5B                  <1> 	pop	ebx
  2529 00004CCF 58                  <1> 	pop	eax
  2530 00004CD0 C3                  <1> 	retn	; 08/06/2015
  2531                              <1> passc_2:
  2532 00004CD1 C705[17670000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2532 00004CD9 0000                <1>
  2533                              <1> 	;pop 	ebx
  2534                              <1> 	;pop	eax
  2535 00004CDB E928E5FFFF          <1> 	jmp	error
  2536                              <1> 
  2537                              <1> writei:
  2538                              <1> 	; 13/06/2022
  2539                              <1> 	; 03/02/2022
  2540                              <1> 	; 20/05/2015
  2541                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2542                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2543                              <1> 	;
  2544                              <1> 	; Write data to file with inode number in R1
  2545                              <1> 	; 
  2546                              <1> 	; INPUTS ->
  2547                              <1> 	;    r1 - inode number
  2548                              <1> 	;    u.count - byte count to be written
  2549                              <1> 	;    u.base - points to user buffer
  2550                              <1> 	;    u.fofp - points to word with current file offset
  2551                              <1> 	; OUTPUTS ->
  2552                              <1> 	;    u.count - cleared
  2553                              <1> 	;    u.nread - accumulates total bytes passed back	
  2554                              <1> 	; ((AX = R1))
  2555                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2556                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2557                              <1> 
  2558 00004CE0 31C9                <1> 	xor	ecx, ecx
  2559 00004CE2 890D[F0660000]      <1> 	mov 	[u.nread], ecx  ; 0
  2560                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2561                              <1> 		            ; / read or write calls
  2562 00004CE8 66890D[27670000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2563 00004CEF 390D[EC660000]      <1> 	cmp 	[u.count], ecx
  2564                              <1> 	;	; tst u.count / test the byte count specified by the user
  2565 00004CF5 770B                <1> 	ja 	short writei_1 ; 1f
  2566                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2567                              <1> 
  2568                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2569 00004CF7 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2570 00004CFA 7505                <1> 	jne	short writei_0
  2571 00004CFC E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2572                              <1> writei_0:
  2573 00004D01 C3                  <1> 	retn
  2574                              <1> 	;	; rts r0 / no, return - no writing to do
  2575                              <1> writei_1: ;1:
  2576                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2577 00004D02 6683F828            <1> 	cmp 	ax, 40
  2578                              <1> 		; cmp r1,$40.
  2579                              <1> 		; / does the i-node number indicate a special file?
  2580                              <1> 	;ja	dskw 
  2581                              <1> 		; bgt dskw / no, branch to standard file output
  2582                              <1> 	; 03/02/2022
  2583 00004D06 7605                <1> 	jna	short writei_3
  2584 00004D08 E958010000          <1> 	jmp	dskw
  2585                              <1> writei_3:
  2586                              <1> 	; (20/05/2015)
  2587 00004D0D 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2588 00004D0E 0FB6D8              <1> 	movzx	ebx, al
  2589                              <1> 	; 03/02/2022
  2590 00004D11 C1E302              <1> 	shl	ebx, 2
  2591                              <1> 	;shl	bx, 2
  2592                              <1> 		; asl r1 / yes, calculate the index into the special file
  2593 00004D14 81C3[184D0000]      <1> 	add	ebx, writei_2 - 4
  2594 00004D1A FF23                <1> 	jmp	dword [ebx]	
  2595                              <1> 		; jmp *1f-2(r1)
  2596                              <1> 		; / jump table and jump to the appropriate routine
  2597                              <1> writei_2: ;1:
  2598 00004D1C [684D0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2599                              <1> 		 ;wtty / tty; r1=2
  2600                              <1> 		 ;wppt / ppt; r1=4
  2601 00004D20 [BB4D0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2602                              <1> 		 ;wmem / mem; r1=6
  2603                              <1> 		 ;wrf0 / rf0
  2604                              <1> 		 ;wrk0 / rk0
  2605                              <1> 		 ;wtap / tap0
  2606                              <1> 		 ;wtap / tap1
  2607                              <1> 		 ;wtap / tap2
  2608                              <1> 		 ;wtap / tap3
  2609                              <1> 		 ;wtap / tap4
  2610                              <1> 		 ;wtap / tap5
  2611                              <1> 		 ;wtap / tap6
  2612                              <1> 		 ;wtap / tap7
  2613 00004D24 [29540000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2614 00004D28 [29540000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2615 00004D2C [29540000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2616 00004D30 [29540000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2617 00004D34 [29540000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2618 00004D38 [29540000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2619 00004D3C [EB4D0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2620 00004D40 [B54D0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2621                              <1> 		 ;xmtt / tty0
  2622 00004D44 [B54D0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2623                              <1> 		 ;xmtt / tty1
  2624 00004D48 [B54D0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2625                              <1> 		 ;xmtt / tty2
  2626 00004D4C [B54D0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2627                              <1> 		 ;xmtt / tty3
  2628 00004D50 [B54D0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2629                              <1> 		 ;xmtt / tty4
  2630 00004D54 [B54D0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2631                              <1> 		 ;xmtt / tty5
  2632 00004D58 [B54D0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2633                              <1> 		 ;xmtt / tty6
  2634 00004D5C [B54D0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2635                              <1> 		 ;xmtt / tty7
  2636 00004D60 [B54D0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2637                              <1> 		; / wlpr / lpr
  2638 00004D64 [B54D0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2639                              <1> 
  2640                              <1> wtty: ; write to console tty (write to screen)
  2641                              <1> 	; 03/02/2022
  2642                              <1> 	; 18/11/2015
  2643                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2644                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2645                              <1> 	;
  2646                              <1> 	; Console tty output is on current video page
  2647                              <1> 	; Console tty character output procedure is changed here
  2648                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2649                              <1> 	;
  2650 00004D68 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2651 00004D6F 8AA3[23640000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2652 00004D75 88E0                <1> 	mov	al, ah ; 07/07/2014
  2653                              <1> wttys:	
  2654                              <1> 	; 10/10/2013
  2655 00004D77 8825[16670000]      <1> 	mov 	[u.ttyn], ah
  2656                              <1> 	; 13/01/2014
  2657 00004D7D FEC0                <1> 	inc	al
  2658 00004D7F A2[F9660000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2659                              <1> wtty_nc: ; 15/05/2013
  2660                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2661 00004D84 E881010000          <1> 	call	cpass
  2662                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2663                              <1> 		             ; / none go to return address in syswrite
  2664                              <1> 		; tst r1 / is character = null
  2665                              <1> 		; beq wtty / yes, get next character
  2666                              <1> 	; 10/10/2013
  2667 00004D89 7428                <1> 	jz	short wret
  2668                              <1> 	;1 :
  2669                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2670                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2671                              <1> 		;	          / than 20
  2672                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2673                              <1> 	; 27/06/2014
  2674                              <1> wtty_1:
  2675                              <1> 	; AH = tty number
  2676                              <1> 	; AL = ASCII code of the character
  2677                              <1> 	; 15/04/2014
  2678                              <1> 	;push	ax
  2679                              <1> 	; 03/02/2022
  2680 00004D8B 50                  <1> 	push	eax
  2681 00004D8C E8360A0000          <1> 	call	putc ; 14/05/2013
  2682 00004D91 731D                <1> 	jnc	short wtty_2
  2683                              <1> 	; 18/11/2015
  2684 00004D93 E818F9FFFF          <1> 	call	idle
  2685                              <1> 	;mov	ax, [esp]
  2686                              <1> 	; 03/02/2022
  2687 00004D98 8B0424              <1> 	mov	eax, [esp]
  2688 00004D9B E8270A0000          <1> 	call	putc
  2689 00004DA0 730E                <1> 	jnc	short wtty_2 
  2690                              <1> 	; 02/06/2014
  2691 00004DA2 8A25[16670000]      <1> 	mov	ah, [u.ttyn]
  2692 00004DA8 E890F9FFFF          <1> 	call	sleep
  2693                              <1> 	; 03/02/2022
  2694 00004DAD 58                  <1> 	pop	eax
  2695                              <1> 	;pop	ax
  2696 00004DAE EBDB                <1> 	jmp 	short wtty_1
  2697                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2698                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2699                              <1> 			      ; / console tty and
  2700                              <1> 		; br 	2f / place character in list; if none available
  2701                              <1> 		   	  ; / branch to put process to sleep
  2702                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2703                              <1> wtty_2:
  2704                              <1> 	; 15/04/2014
  2705                              <1> 	;pop	ax
  2706                              <1> 	; 03/02/2022
  2707 00004DB0 58                  <1> 	pop	eax
  2708 00004DB1 EBD1                <1> 	jmp	short wtty_nc
  2709                              <1> 		; br wtty
  2710                              <1> wret:	; 10/10/2013 (20/05/2015)
  2711 00004DB3 58                  <1> 	pop	eax
  2712 00004DB4 C3                  <1> 	retn
  2713                              <1> 	;2:
  2714                              <1> 		;mov	r1,-(sp) / place character on stack
  2715                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2716                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2717                              <1> 		;br	1b / try again to place character in clist and output
  2718                              <1> 
  2719                              <1> xmtt:   ; < send/write character to tty >
  2720                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2721                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2722                              <1> 	;
  2723                              <1> 	; Retro UNIX 8086 v1 modification !
  2724                              <1> 	; 
  2725                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2726                              <1> 	;		(exactly different than this one)
  2727                              <1> 	;	was in 'u9.s' file.
  2728                              <1> 	;
  2729 00004DB5 2C0A                <1> 	sub 	al, 10
  2730                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2731                              <1> 	; 10/10/2013
  2732 00004DB7 88C4                <1> 	mov	ah, al
  2733                              <1> 	; 28/07/2013
  2734 00004DB9 EBBC                <1> 	jmp	short wttys
  2735                              <1> 
  2736                              <1> ;wppt:
  2737                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2738                              <1> ;		         / if none return to writei's calling routine
  2739                              <1> ;	jsr	r0,pptoc / output character on ppt
  2740                              <1> ;	br	wppt
  2741                              <1> 
  2742                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2743                              <1> 	; 17/10/2015
  2744                              <1> 	; 11/06/2015
  2745                              <1> 	; 24/05/2015
  2746                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2747                              <1> 	;
  2748 00004DBB 813D[0A070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2748 00004DC1 [D3460000]          <1>
  2749 00004DC5 7415                <1>         je      short wmem_acc_err
  2750                              <1> 	;
  2751 00004DC7 8B35[D8660000]      <1>         mov     esi, [u.fofp] 
  2752                              <1> wmem_1:
  2753 00004DCD E838010000          <1> 	call	cpass
  2754                              <1> 		; jsr r0,cpass / get next character from users area of
  2755                              <1> 			     ; / core and put it in r1
  2756                              <1>         	; mov r1,-(sp) / put character on the stack
  2757                              <1> 	; 20/09/2013
  2758 00004DD2 74DF                <1> 	jz	short wret ; wmem_2  
  2759 00004DD4 8B1E                <1>         mov     ebx, [esi]
  2760                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2761 00004DD6 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2762                              <1> 		; inc *u.fofp / increment file offset to point to next
  2763                              <1> 			    ; / available location in file
  2764 00004DD8 8803                <1> 	mov	[ebx], al	
  2765                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2766                              <1> 			        ; / assigned to it
  2767 00004DDA EBF1                <1> 	jmp	short wmem_1
  2768                              <1> 		; br wmem / continue
  2769                              <1> 	;1:
  2770                              <1> 	;jmp	error / ?
  2771                              <1> ;wmem_2:	
  2772                              <1> ;	; 20/09/2013
  2773                              <1> ;	pop	ax
  2774                              <1> ;	retn
  2775                              <1> 
  2776                              <1> wmem_acc_err:
  2777 00004DDC C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2777 00004DE4 0000                <1>
  2778 00004DE6 E91DE4FFFF          <1> 	jmp	error
  2779                              <1> 
  2780                              <1> ;wlpr:
  2781                              <1> 	; 13/06/2022
  2782                              <1>         ;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2783                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2784                              <1> 		;/	jsr	r0,cpass
  2785                              <1> 		;/	cmp	r0,$'a
  2786                              <1> 		;/	blo	1f
  2787                              <1> 		;/	cmp	r1,$'z
  2788                              <1> 		;/	bhi	1f
  2789                              <1> 		;/	sub	$40,r1
  2790                              <1> 		;/1:
  2791                              <1> 		;/	jsr	r0,lptoc
  2792                              <1> 		;/	br	wlpr
  2793                              <1> 		; br rmem / continue
  2794                              <1> 
  2795                              <1> ; 13/06/2022 - Retro UNIX 386 v1 - PRINTER BIOS (Functions)
  2796                              <1> 
  2797                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2798                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2799                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2800                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2801                              <1> 
  2802                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2803                              <1> 
  2804                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2805                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2806                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2807                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2808                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2809                              <1> RESERVED	equ 00000110b	; NOPS
  2810                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2811                              <1> 
  2812                              <1> ;----------------------------------------------------------------
  2813                              <1> ;								:
  2814                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2815                              <1> ;								:
  2816                              <1> ;   CX has count of bytes to be printed 			:
  2817                              <1> ;   ES:DI point to source buffer contains characters		:
  2818                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2819                              <1> ;								:
  2820                              <1> ;----------------------------------------------------------------
  2821                              <1> 
  2822                              <1> wlpr:
  2823                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2824                              <1> PRN$WRIT:
  2825                              <1> 	; INPUT:
  2826                              <1> 	;	[u.count] = count of characters to be printed
  2827                              <1> 	;	[u.base] = buffer address in user's memory space
  2828                              <1> 	;
  2829                              <1> 	;	(if ECX = 0, printer status will be returned)
  2830                              <1> 	
  2831                              <1> 	;xor	ebx, ebx
  2832                              <1> PRN$LOOP:
  2833 00004DEB E81A010000          <1> 	call	cpass		  ; Get a character into AL
  2834 00004DF0 7431                <1> 	jz	short pr_exit
  2835                              <1> 	;
  2836 00004DF2 B302                <1> 	mov	bl, 2  ; retry count
  2837                              <1> PRN$OUT:
  2838                              <1> 	; al = character which will be printed
  2839 00004DF4 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2840 00004DF6 E850000000          <1> 	call	PRNOP
  2841 00004DFB 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2842                              <1> PrRetry:
  2843                              <1> 	; al = character
  2844 00004DFD FECB                <1> 	dec	bl
  2845 00004DFF 75F3                <1> 	jnz	short PRN$OUT
  2846                              <1> pr_err_exit:
  2847 00004E01 0FB6C0              <1> 	movzx	eax, al
  2848 00004E04 A3[17670000]        <1> 	mov	[u.error], eax
  2849 00004E09 A3[C8660000]        <1> 	mov	[u.r0], eax ; error code in AL
  2850 00004E0E 8B2D[C0660000]      <1> 	mov 	ebp, [u.sp]
  2851                              <1> 			; Kernel stack at the beginning of sys call
  2852 00004E14 8B15[F0660000]      <1> 	mov	edx, [u.nread]
  2853 00004E1A 4A                  <1> 	dec	edx ; last char failed
  2854 00004E1B 895514              <1> 	mov	[ebp+20], edx ; count of printed chacters in edx
  2855 00004E1E E9E5E3FFFF          <1> 	jmp	error
  2856                              <1> pr_exit:
  2857 00004E23 58                  <1> 	pop	eax ; inode number
  2858                              <1> 
  2859                              <1> 	;mov	eax, [u.nread]
  2860                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2861                              <1> 	;jmp	sysret
  2862 00004E24 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2863                              <1> 
  2864                              <1> ; 13/06/2022
  2865                              <1> 
  2866                              <1> ;----------------------------------------------------------------
  2867                              <1> ;								:
  2868                              <1> ;		PRINTER STATUS ROUTINE				:
  2869                              <1> ;								:
  2870                              <1> ;----------------------------------------------------------------
  2871                              <1> ;
  2872                              <1> 
  2873                              <1> lpr_stat:
  2874                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2875                              <1> PRN$STAT:
  2876 00004E25 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2877 00004E2A 750E                <1> 	jnz	short prn_stat_retn
  2878                              <1> 				  ; if error jump to error routine
  2879                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2880 00004E2C B01F                <1> 	mov	al, ERR_PRN_PAPER
  2881 00004E2E F6C420              <1> 	test	ah, NOPAPERSTATUS
  2882 00004E31 7507                <1> 	jnz	short prn_stat_retn
  2883 00004E33 F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2884 00004E36 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2885 00004E38 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2886                              <1> prn_stat_retn:
  2887                              <1> 	; al = error code
  2888                              <1> 	; ah = status flags
  2889 00004E3A A3[C8660000]        <1> 	mov	[u.r0], eax
  2890                              <1> 	;movzx	eax, al
  2891                              <1> 	;mov 	[u.error], eax
  2892 00004E3F 58                  <1> 	pop	eax ; discard return address to syswrite
  2893 00004E40 E9E3E3FFFF          <1> 	jmp	sysret
  2894                              <1> prn_stat_ok:
  2895 00004E45 30C0                <1> 	xor	al, al ; 0
  2896 00004E47 EBF1                <1> 	jmp	short prn_stat_retn
  2897                              <1> 
  2898                              <1> ;
  2899                              <1> ;   PRNSTAT	get printer status
  2900                              <1> ;   PRNOP	print a character
  2901                              <1> ;
  2902                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2903                              <1> ; printer routines.  The routines share code which calls on the bios and
  2904                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2905                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2906                              <1> ;
  2907                              <1> ;   INPUT	if PRNOP then character in AL
  2908                              <1> ;
  2909                              <1> ;   OUTPUT	- AL holds error code
  2910                              <1> ;		- AH status byte from printer
  2911                              <1> ;		- flag NZ if error
  2912                              <1> 
  2913                              <1> PRNSTAT:
  2914 00004E49 B402                <1> 	mov	ah, 2		  ; set command for get status 
  2915                              <1> 
  2916                              <1> PRNOP:
  2917                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2918                              <1> 	;
  2919                              <1> 	; Print character (on paper)
  2920                              <1> 
  2921                              <1> 	; INPUT:
  2922                              <1> 	;	al = character to be printed
  2923                              <1> 	; OUTPUT:
  2924                              <1> 	;	zf = 1 -> ok
  2925                              <1> 	;	zf = 0 -> error code in AL
  2926                              <1> 
  2927 00004E4B E8B00B0000          <1> 	call	int17h	 ; call lpt bios
  2928                              <1> 	
  2929 00004E50 F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  2930 00004E53 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  2931                              <1> 
  2932                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  2933                              <1> 	; THE CONVERSE IS NOT TRUE.
  2934                              <1> 
  2935                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  2936 00004E55 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2937 00004E57 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  2938 00004E5A 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  2939                              <1> 	;mov	al, ERR_PRN_IO
  2940 00004E5C FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  2941                              <1> PRNOP1: 
  2942                              <1> 
  2943                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  2944                              <1> 
  2945 00004E5E C3                  <1> 	retn			  ; RETURN WITH ERROR
  2946                              <1>  
  2947                              <1> ; THE BITS SAID NO ERROR.
  2948                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  2949                              <1> 
  2950                              <1> prnop_chk_nrdy:
  2951                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  2952 00004E5F B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  2953                              <1> 	
  2954 00004E61 F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  2955                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  2956                              <1> PRNOP2: 
  2957 00004E64 C3                  <1> 	retn
  2958                              <1> 
  2959                              <1> 
  2960                              <1> dskw: ; / write routine for non-special files
  2961                              <1> 	;
  2962                              <1> 	; 03/02/2022
  2963                              <1> 	; 25/07/2015
  2964                              <1> 	; 16/06/2015
  2965                              <1> 	; 09/06/2015
  2966                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2967                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2968                              <1> 	;
  2969                              <1> 	; 01/08/2013 (mkdir_w check)
  2970                              <1> 
  2971                              <1> 	;push	ax ; 26/04/2013
  2972                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2973                              <1> 	; 03/02/2022
  2974 00004E65 50                  <1> 	push	eax
  2975                              <1> 	; AX = inode number
  2976 00004E66 E8B3FAFFFF          <1> 	call	iget
  2977                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2978                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2979 00004E6B 8B1D[D8660000]      <1>         mov     ebx, [u.fofp] 
  2980 00004E71 8B13                <1> 	mov 	edx, [ebx]
  2981                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2982                              <1> 			       ; / in the fsp entry for this file] in r2
  2983 00004E73 0315[EC660000]      <1> 	add 	edx, [u.count]	
  2984                              <1> 		; add u.count,r2 / no. of bytes to be written
  2985                              <1> 			       ; / + file offset is put in r2
  2986                              <1> 	; 16/06/2015        
  2987 00004E79 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2988 00004E7F 760F                <1> 	jna	short dskw_0
  2989 00004E81 C705[17670000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2989 00004E89 0000                <1>
  2990 00004E8B E978E3FFFF          <1> 	jmp	error
  2991                              <1> dskw_0:	
  2992 00004E90 663B15[C8630000]    <1> 	cmp     dx, [i.size]
  2993                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2994                              <1> 		              ; / the file?
  2995 00004E97 760C                <1> 	jna	short dskw_1
  2996                              <1> 		; blos 1f / no, branch
  2997 00004E99 668915[C8630000]    <1>         mov     [i.size], dx
  2998                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2999                              <1> 			      ; / file offset + no. of data bytes
  3000 00004EA0 E883FBFFFF          <1> 	call	setimod
  3001                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3002                              <1> 		          ; / modified), stuff time of modification into
  3003                              <1> 	          	  ; / core image of i-node
  3004                              <1> dskw_1: ; 1:	
  3005 00004EA5 E80BF9FFFF          <1> 	call	mget
  3006                              <1> 	; eAX = Block number
  3007                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3008                              <1> 			    ; /	the next data byte
  3009                              <1> 	; eax = block number
  3010 00004EAA 8B1D[D8660000]      <1> 	mov     ebx, [u.fofp]
  3011 00004EB0 8B13                <1> 	mov	edx, [ebx]
  3012 00004EB2 81E2FF010000        <1> 	and	edx, 1FFh  
  3013                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3014 00004EB8 750C                <1> 	jnz	short dskw_2
  3015                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3016                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3017 00004EBA 813D[EC660000]0002- <1> 	cmp	dword [u.count], 512
  3017 00004EC2 0000                <1>
  3018                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3019                              <1> 				  ; / an entire block? (i.e., no. of
  3020 00004EC4 7305                <1> 	jnb	short dskw_3
  3021                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3022                              <1> 			; / Yes, branch. Don't have to read block
  3023                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3024                              <1>    		; / overwritten).
  3025 00004EC6 E824060000          <1> 	call	dskrd
  3026                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3027                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3028                              <1> dskw_3: ; 3:
  3029                              <1> 	; eAX (r1) = block/sector number
  3030 00004ECB E891060000          <1> 	call	wslot
  3031                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3032                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3033 00004ED0 803D[29670000]00    <1> 	cmp	byte [u.kcall], 0
  3034 00004ED7 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3035                              <1> 	;
  3036 00004ED9 66833D[27670000]00  <1> 	cmp	word [u.pcount], 0
  3037 00004EE1 7705                <1> 	ja	short dskw_5
  3038                              <1> dskw_4:
  3039                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3040 00004EE3 E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3041                              <1> dskw_5:
  3042                              <1> 	; eBX (r5) = system (I/O) buffer address
  3043 00004EE8 E87D000000          <1> 	call	sioreg
  3044                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3045                              <1> 			     ; / r1 = address of data, r2 points to location
  3046                              <1> 			     ; / in buffer in which to start writing data
  3047                              <1> 	; eSI = file (user data) offset
  3048                              <1> 	; eDI = sector (I/O) buffer offset
  3049                              <1> 	; eCX = byte count
  3050                              <1> 	;
  3051 00004EED F3A4                <1>   	rep	movsb
  3052                              <1> 		; movb (r1 )+,(r2)+ 
  3053                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3054                              <1> 		; dec r3 / decrement no. of bytes to be written
  3055                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3056                              <1> 	; 25/07/2015
  3057                              <1> 	; eax = remain bytes in buffer
  3058                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3059 00004EEF 09C0                <1> 	or	eax, eax
  3060 00004EF1 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3061                              <1> dskw_6:
  3062 00004EF3 E885060000          <1> 	call	dskwr
  3063                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3064 00004EF8 833D[EC660000]00    <1>         cmp     dword [u.count], 0
  3065                              <1> 		; tst u.count / any more data to write?
  3066 00004EFF 77A4                <1> 	ja	short dskw_1
  3067                              <1> 		; bne 1b / yes, branch
  3068                              <1> 	; 03/08/2013
  3069 00004F01 C605[29670000]00    <1> 	mov	byte [u.kcall], 0
  3070                              <1> 	; 20/09/2013 (;;)
  3071                              <1> 	;pop	ax
  3072                              <1> 	; 03/02/2022
  3073 00004F08 58                  <1> 	pop	eax
  3074 00004F09 C3                  <1> 	retn
  3075                              <1> 	;;jmp 	short dskw_ret 
  3076                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3077                              <1> 
  3078                              <1> cpass: ; / get next character from user area of core and put it in r1
  3079                              <1> 	; 18/10/2015
  3080                              <1> 	; 10/10/2015
  3081                              <1> 	; 10/07/2015
  3082                              <1> 	; 02/07/2015
  3083                              <1> 	; 01/07/2015
  3084                              <1> 	; 24/06/2015
  3085                              <1> 	; 08/06/2015
  3086                              <1> 	; 04/06/2015
  3087                              <1> 	; 20/05/2015
  3088                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3089                              <1> 	;
  3090                              <1> 	; INPUTS -> 
  3091                              <1> 	;     [u.base] = virtual address in user area
  3092                              <1> 	;     [u.count] = byte count (max.)
  3093                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3094                              <1> 	; OUTPUTS -> 
  3095                              <1> 	;     AL = the character which is pointed by [u.base]
  3096                              <1> 	;     zf = 1 -> transfer count has been completed	
  3097                              <1>         ;
  3098                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3099                              <1> 	;
  3100                              <1> 	;
  3101 00004F0A 833D[EC660000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3102                              <1> 		; tst u.count / have all the characters been transferred
  3103                              <1> 			    ; / (i.e., u.count, # of chars. left
  3104 00004F11 763F                <1> 	jna	short cpass_3
  3105                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3106 00004F13 FF0D[EC660000]      <1> 	dec	dword [u.count]
  3107                              <1> 		; dec u.count / no, decrement u.count
  3108                              <1>         ; 19/05/2015 
  3109                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3110                              <1> 	;		      to physical address
  3111 00004F19 66833D[27670000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3112                              <1> 			     ; 1-4095 --> use previous physical base address
  3113                              <1> 			     ; in [u.pbase]
  3114 00004F21 770E                <1> 	ja	short cpass_1
  3115                              <1> 	; 02/07/2015
  3116 00004F23 833D[1F670000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3117 00004F2A 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3118                              <1> 	; 08/06/2015 - 10/07/2015
  3119 00004F2C E852FDFFFF          <1> 	call	trans_addr_r
  3120                              <1> cpass_1:
  3121                              <1> 	; 02/07/2015
  3122                              <1> 	; 24/06/2015
  3123 00004F31 66FF0D[27670000]    <1> 	dec	word [u.pcount]
  3124                              <1> cpass_2: 
  3125                              <1> 	; 10/10/2015
  3126                              <1> 	; 02/07/2015
  3127 00004F38 8B15[23670000]      <1> 	mov	edx, [u.pbase]
  3128 00004F3E 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3129                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3130                              <1> 				; / by u.base and put it in r1
  3131 00004F40 FF05[F0660000]      <1> 	inc	dword [u.nread]
  3132                              <1> 		; inc u.nread / increment no. of bytes transferred
  3133 00004F46 FF05[E8660000]      <1> 	inc	dword [u.base]
  3134                              <1> 		; inc u.base / increment the buffer address to point to the
  3135                              <1> 			   ; / next byte
  3136 00004F4C FF05[23670000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3137                              <1> cpass_3:
  3138 00004F52 C3                  <1> 	retn
  3139                              <1> 		; rts	r0 / next byte
  3140                              <1> 	; 1: 
  3141                              <1> 		; mov (sp)+,r0 
  3142                              <1> 		         ; / put return address of calling routine into r0
  3143                              <1> 		; mov (sp)+,r1 / i-number in r1
  3144                              <1> 		; rts r0 / non-local return
  3145                              <1> cpass_k:
  3146                              <1> 	; 02/07/2015
  3147                              <1> 	; The caller is os kernel 
  3148                              <1> 	; (get sysexec arguments from kernel's memory space)
  3149                              <1> 	;
  3150 00004F53 8B1D[E8660000]      <1> 	mov	ebx, [u.base]
  3151 00004F59 66C705[27670000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3151 00004F61 10                  <1>
  3152 00004F62 891D[23670000]      <1> 	mov	[u.pbase], ebx
  3153 00004F68 EBCE                <1> 	jmp	short cpass_2
  3154                              <1> 	
  3155                              <1> sioreg: 
  3156                              <1> 	; 25/07/2015
  3157                              <1> 	; 18/07/2015
  3158                              <1> 	; 02/07/2015
  3159                              <1> 	; 17/06/2015
  3160                              <1> 	; 09/06/2015
  3161                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3162                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3163                              <1> 	;
  3164                              <1> 	; INPUTS -> 
  3165                              <1> 	;     eBX = system buffer (data) address (r5)
  3166                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3167                              <1> 	;     [u.base] = virtual address of the user buffer
  3168                              <1> 	;     [u.pbase] = physical address of the user buffer
  3169                              <1> 	;     [u.count] = byte count
  3170                              <1> 	;     [u.pcount] = byte count within page frame 			
  3171                              <1> 	; OUTPUTS -> 
  3172                              <1> 	;     eSI = user data offset (r1)
  3173                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3174                              <1> 	;     eCX = byte count (r3)
  3175                              <1> 	;     EAX = remain bytes after byte count within page frame
  3176                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3177                              <1>         ;
  3178                              <1> 	; ((Modified registers:  EDX))
  3179                              <1>  
  3180 00004F6A 8B35[D8660000]      <1>         mov     esi, [u.fofp]
  3181 00004F70 8B3E                <1>         mov     edi, [esi]
  3182                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3183 00004F72 89F9                <1> 	mov	ecx, edi
  3184                              <1> 		; mov r2,r3 / and also to r3
  3185 00004F74 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3186                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3187 00004F7A 81E7FF010000        <1> 	and	edi, 1FFh
  3188                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3189 00004F80 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3190                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3191                              <1> 			  ; / where data is to be placed
  3192                              <1>                 ; mov u.base,r1 / address of data is in r1
  3193 00004F82 F7D9                <1> 	neg	ecx
  3194                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3195                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3196 00004F84 3B0D[EC660000]      <1> 	cmp	ecx, [u.count]
  3197                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3198                              <1> 			       ; / to be written to the file
  3199 00004F8A 7606                <1> 	jna	short sioreg_0
  3200                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3201                              <1> 			 ; / in the file block as the number to be written
  3202 00004F8C 8B0D[EC660000]      <1> 	mov	ecx, [u.count]
  3203                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3204                              <1> 			       ; / bytes as the number to be written
  3205                              <1> sioreg_0:
  3206                              <1> 	; 17/06/2015
  3207 00004F92 803D[29670000]00    <1> 	cmp	byte [u.kcall], 0 
  3208 00004F99 7613                <1> 	jna	short sioreg_1
  3209                              <1> 	; 25/07/2015
  3210                              <1> 	; the caller is 'mkdir' or 'namei'
  3211 00004F9B A1[E8660000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3212 00004FA0 A3[23670000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3213 00004FA5 66890D[27670000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3214 00004FAC EB0B                <1> 	jmp	short sioreg_2
  3215                              <1> sioreg_1:
  3216                              <1> 	; 25/07/2015
  3217                              <1> 	; 18/07/2015
  3218                              <1> 	; 09/06/2015 
  3219 00004FAE 0FB715[27670000]    <1> 	movzx	edx, word [u.pcount]
  3220                              <1> 		; ecx and [u.pcount] are always > 0, here
  3221 00004FB5 39D1                <1> 	cmp	ecx, edx	
  3222 00004FB7 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3223                              <1> sioreg_2: ; 2:
  3224 00004FB9 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3225                              <1> sioreg_3:
  3226 00004FBB 010D[F0660000]      <1> 	add 	[u.nread], ecx
  3227                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3228                              <1> 			         ; / during write is put into u.nread
  3229 00004FC1 290D[EC660000]      <1> 	sub 	[u.count], ecx
  3230                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3231                              <1> 			       ; / must be written or read
  3232 00004FC7 010D[E8660000]      <1> 	add 	[u.base], ecx
  3233                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3234                              <1> 			      ; / data bytes
  3235 00004FCD 010E                <1>         add 	[esi], ecx 
  3236                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3237                              <1> 			       ; / + old file offset
  3238                              <1> 	; 25/07/2015
  3239 00004FCF 8B35[23670000]      <1> 	mov	esi, [u.pbase]
  3240 00004FD5 66290D[27670000]    <1> 	sub	[u.pcount], cx
  3241 00004FDC 010D[23670000]      <1> 	add	[u.pbase], ecx
  3242 00004FE2 C3                  <1>         retn
  3243                              <1> 		; rts r0
  3244                              <1> 		; transfer count > [u.pcount]
  3245                              <1> sioreg_4:
  3246                              <1> 	; 25/07/2015
  3247                              <1> 	; transfer count > [u.pcount] 
  3248                              <1> 	; (ecx > edx)
  3249 00004FE3 89C8                <1> 	mov	eax, ecx
  3250 00004FE5 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3251 00004FE7 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3252 00004FE9 EBD0                <1> 	jmp	short sioreg_3
  2055                                  %include 'u7.s'        ; 18/04/2015
  2056                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS7.INC
  2057                              <1> ; Last Modification: 13/06/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 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2068                              <1> ;
  2069                              <1> ; ****************************************************************************
  2070                              <1> ; 14/11/2015
  2071                              <1> 
  2072                              <1> sysmount: ; / mount file system; args special; name
  2073                              <1> 	; 14/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2074                              <1> 	; 12/02/2022
  2075                              <1> 	; 04/02/2022
  2076                              <1> 	; 14/11/2015
  2077                              <1> 	; 24/10/2015
  2078                              <1> 	; 13/10/2015
  2079                              <1> 	; 10/07/2015
  2080                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2081                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2082                              <1> 	;
  2083                              <1> 	; 'sysmount' anounces to the system that a removable 
  2084                              <1> 	; file system has been mounted on a special file.
  2085                              <1> 	; The device number of the special file is obtained vihha
  2086                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2087                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2088                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2089                              <1> 	; to read file system into core, i.e. the first block on the
  2090                              <1> 	; mountable file system is read in. This block is super block
  2091                              <1> 	; for the file system. This call is super user restricted.	
  2092                              <1> 	;
  2093                              <1> 	; Calling sequence:
  2094                              <1> 	;	sysmount; special; name
  2095                              <1> 	; Arguments:
  2096                              <1> 	;	special - pointer to name of special file (device)
  2097                              <1> 	;	name -  pointer to name of the root directory of the
  2098                              <1> 	;		newly mounted file system. 'name' should 
  2099                              <1> 	;		always be a directory.
  2100                              <1> 	; Inputs: - 
  2101                              <1> 	; Outputs: -
  2102                              <1> 	; ...............................................................
  2103                              <1> 	;				
  2104                              <1> 	; Retro UNIX 8086 v1 modification: 
  2105                              <1> 	;       'sysmount' system call has two arguments; so,
  2106                              <1> 	;	* 1st argument, special is pointed to by BX register
  2107                              <1> 	;	* 2nd argument, name is in CX register
  2108                              <1> 	;
  2109                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2110                              <1> 	;	       already modified for IBM PC compatibility and 
  2111                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2112                              <1> 	
  2113                              <1> 	;call	arg2
  2114                              <1> 		; jsr r0,arg2 / get arguments special and name
  2115 00004FEB 891D[E0660000]      <1> 	mov	[u.namep], ebx
  2116                              <1> 	; 12/02/2022
  2117                              <1> 	;push	ecx ; directory name
  2118 00004FF1 66833D[B2660000]00  <1> 	cmp	word [mnti], 0
  2119                              <1> 		; tst mnti / is the i-number of the cross device file
  2120                              <1> 			 ; / zero?
  2121                              <1> 	;;ja	error
  2122                              <1>         	; bne errora / no, error
  2123                              <1> 	;ja	sysmnt_err0
  2124                              <1> 	; 04/02/2022
  2125 00004FF9 7605                <1> 	jna	short sysmnt_0
  2126 00004FFB E950010000          <1> 	jmp	sysmnt_err0
  2127                              <1> sysmnt_0:
  2128                              <1> 	; 12/02/2022
  2129 00005000 51                  <1> 	push	ecx ; directory name
  2130 00005001 E859010000          <1> 	call	getspl
  2131                              <1> 		; jsr r0,getspl / get special files device number in r1
  2132                              <1> 	; 12/02/2022
  2133 00005006 8F05[E0660000]      <1> 	pop	dword [u.namep] ; directory name
  2134                              <1> 	; 13/10/2015
  2135                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2136                              <1> 	; 04/02/2022
  2137 0000500C 29DB                <1> 	sub	ebx, ebx
  2138 0000500E 88C3                <1> 	mov	bl, al
  2139 00005010 F683[4E5E0000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2140 00005017 750F                <1> 	jnz	short sysmnt_1
  2141                              <1> sysmnt_err1:
  2142 00005019 C705[17670000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2142 00005021 0000                <1>
  2143 00005023 E9E0E1FFFF          <1> 	jmp	error
  2144                              <1> sysmnt_1:
  2145                              <1> 	; 12/02/2022
  2146                              <1> 	;pop	dword [u.namep]
  2147                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2148                              <1> 				  ; / on the device
  2149                              <1> 	; 14/11/2015
  2150 00005028 53                  <1> 	push	ebx ; 13/10/2015
  2151                              <1> 		; mov r1,-(sp) / save the device number
  2152                              <1>         ;
  2153 00005029 E8DBF0FFFF          <1> 	call	namei
  2154                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2155                              <1> 		       ; ax = 0 -> file not found 	
  2156                              <1> 	;jz	error
  2157                              <1> 	;jc	error
  2158                              <1> 		; jsr r0,namei / get the i-number of the file
  2159                              <1>                	; br errora
  2160 0000502E 730F                <1> 	jnc	short sysmnt_2
  2161                              <1> sysmnt_err2:
  2162 00005030 C705[17670000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2162 00005038 0000                <1>
  2163 0000503A E9C9E1FFFF          <1> 	jmp	error
  2164                              <1> sysmnt_2:	
  2165 0000503F 66A3[B2660000]      <1> 	mov	[mnti], ax
  2166                              <1>         	; mov r1,mnti / put it in mnti
  2167                              <1> 
  2168                              <1> 	; 14/05/2022
  2169                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2170 00005045 66A1[A8660000]      <1> 	mov	ax, [ii]
  2171 0000504B 66A3[B4660000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2172                              <1> 
  2173                              <1> 	; 04/02/2022
  2174 00005051 BB[80750000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2175                              <1> sysmnt_3: ;1:
  2176                              <1>         ;cmp	byte [ebx+1], 0
  2177                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2178                              <1> 			   ; / dismountable device set?
  2179                              <1>         ;jna	short sysmnt_4		
  2180                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2181                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2182                              <1> 	;jmp	short sysmnt_3
  2183                              <1> sysmnt_4:   
  2184 00005056 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2185 00005057 A2[AF660000]        <1> 	mov	[mdev], al
  2186                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2187 0000505C 8803                <1> 	mov	[ebx], al
  2188                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2189                              <1> 			      ; / of the I/O queue entry
  2190                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2191                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2192 0000505E 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2193                              <1> 		; bis $2000,sb1 / set the read bit
  2194                              <1> 	; Retro UNIX 386 v1 modification : 
  2195                              <1> 	;	32 bit block number at buffer header offset 4
  2196 00005063 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2197 0000506A E859060000          <1> 	call 	diskio
  2198 0000506F 7345                <1> 	jnc	short sysmnt_5
  2199 00005071 31C0                <1> 	xor 	eax, eax
  2200 00005073 66A3[B2660000]      <1> 	mov	[mnti], ax ; 0
  2201 00005079 A2[AF660000]        <1> 	mov	[mdev], al ; 0
  2202                              <1> 	;mov	[cdev], al ; 0
  2203                              <1> 	; 12/02/2022
  2204 0000507E 803D[2A670000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2205 00005085 7508                <1> 	jne	short sysmnt_err3
  2206                              <1> 	; yes, clear [u.brwdev] for next check
  2207                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2208 00005087 FE05[2A670000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2209 0000508D EB0A                <1> 	jmp	short sysmnt_err4
  2210                              <1> sysmnt_err3:	; 12/02/2022
  2211                              <1> 	; no, set [u.error] to disk read error
  2212 0000508F C705[17670000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2212 00005097 0000                <1>
  2213                              <1> sysmnt_err4:
  2214                              <1> 	; 12/02/2022
  2215                              <1> 	; 14/11/2015
  2216 00005099 FEC8                <1> 	dec 	al
  2217 0000509B 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2218 0000509D FEC0                <1> 	inc	al
  2219 0000509F 48                  <1> 	dec	eax
  2220 000050A0 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2221 000050A3 E960E1FFFF          <1> 	jmp	error
  2222                              <1> sysmnt_invd:
  2223                              <1> 	; 12/02/2022
  2224 000050A8 C705[17670000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2224 000050B0 0000                <1>
  2225                              <1> 				 ;'invalid fs/superblock !' error
  2226 000050B2 30C0                <1> 	xor	al, al
  2227 000050B4 EBE3                <1> 	jmp	short sysmnt_err4
  2228                              <1> 
  2229                              <1> sysmnt_5:
  2230                              <1> 	; 04/02/2022 (BugFix)
  2231                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2232                              <1> 	; (Following check is needed to prevent mounting an
  2233                              <1> 	; invalid valid file system (invalid super block).
  2234                              <1> 	; 
  2235 000050B6 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2236 000050B9 C0E002              <1> 	shl	al, 2 ; 4*index
  2237 000050BC 8B88[325E0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2238                              <1> 	;;shl 	ecx, 3 ; !!!
  2239                              <1> 	; 04/02/2022
  2240 000050C2 C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2241                              <1> 	; ecx = number of free map bytes (required)
  2242                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2243 000050C5 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2244                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2245                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2246 000050C9 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2247                              <1> 			 ; (in sectors), if they are not equal
  2248                              <1> 			 ; the disk to be mounted is an...	
  2249 000050CB 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2250                              <1> 			 ; (which has not got a valid super block)
  2251                              <1> 	;
  2252 000050CD C6430100            <1> 	mov	byte [ebx+1], 0
  2253                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2254                              <1> ;sysmnt_6: ;1:
  2255                              <1> 	;;cmp	byte [sb1+1], 0
  2256                              <1> 		; tstb sb1+1 / done reading?
  2257                              <1>    	;;jna	sysret
  2258                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2259                              <1> 	;;jmp	short sysmnt_6
  2260                              <1> 		;bne 1b / no, wait
  2261                              <1>         	;br sysreta / yes
  2262 000050D1 E952E1FFFF          <1> 	jmp	sysret
  2263                              <1> 
  2264                              <1> sysumount: ; / special dismount file system,
  2265                              <1> 	; 15/05/2022
  2266                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2267                              <1> 	; 04/02/2022
  2268                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2269                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2270                              <1> 	;
  2271                              <1> 	; 04/11/2013
  2272                              <1> 	; 09/07/2013
  2273                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2274                              <1> 	; indicated as an argument is no longer contain a removable
  2275                              <1> 	; file system. 'getspl' gets the device number of the special
  2276                              <1> 	; file. If no file system was mounted on that device an error
  2277                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2278                              <1> 	; to 'sysret'.
  2279                              <1> 	;
  2280                              <1> 	; Calling sequence:
  2281                              <1> 	;	sysmount; special
  2282                              <1> 	; Arguments:
  2283                              <1> 	;	special - special file to dismount (device)
  2284                              <1> 	;
  2285                              <1> 	; Inputs: - 
  2286                              <1> 	; Outputs: -
  2287                              <1> 	; ...............................................................
  2288                              <1> 	;				
  2289                              <1> 	; Retro UNIX 8086 v1 modification: 
  2290                              <1> 	;       'sysumount' system call has one argument; so,
  2291                              <1> 	;	* Single argument, special is pointed to by BX register
  2292                              <1> 	;
  2293                              <1> 	
  2294                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2295                              <1> 	;call	arg
  2296                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2297 000050D6 891D[E0660000]      <1>         mov	[u.namep], ebx
  2298 000050DC E87E000000          <1> 	call	getspl
  2299                              <1> 		; jsr r0,getspl / get the device number in r1
  2300                              <1> 	;;;
  2301                              <1> 	; 09/05/2022 - Erdogan Tan
  2302                              <1> 	; (I have added [mnti] check because
  2303                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2304                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2305                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2306                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2307 000050E1 66833D[B2660000]00  <1> 	cmp	word [mnti], 0
  2308 000050E9 7665                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2309                              <1> 	;;;
  2310                              <1> 
  2311 000050EB 3A05[AF660000]      <1> 	cmp	al, [mdev]
  2312                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2313 000050F1 755D                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2314                              <1> 	;jne	error
  2315                              <1>         	; bne errora / no error
  2316 000050F3 30C0                <1> 	xor	al, al ; ah = 0
  2317                              <1> sysumnt_0: ;1:
  2318                              <1>      	; 04/02/2022
  2319                              <1> 	;cmp 	[sb1+1], al ; 0
  2320                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2321                              <1> 	;		   ; / (inhibit bit set)?
  2322                              <1> 	;jna	short sysumnt_1		
  2323                              <1> 	;	; bne 1b / yes, wait
  2324                              <1> 	;call	idle ; (wait for hardware interrupt)
  2325                              <1> 	;jmp	short sysumnt_0
  2326                              <1> sysumnt_1:
  2327                              <1> 	; 15/05/2022
  2328                              <1> 	; change user's current directory to mounting directory
  2329                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2330 000050F5 3805[0C670000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2331 000050FB 7643                <1> 	jna	short sysumnt_4
  2332                              <1> 	;;;
  2333                              <1> 	; 15/05/2022
  2334                              <1> 	; It is needed to change the parent process's current
  2335                              <1> 	; directory because shell runs (/etc/umount) 
  2336                              <1> 	; as child process.
  2337 000050FD 31DB                <1> 	xor	ebx, ebx 
  2338 000050FF 8A1D[11670000]      <1> 	mov	bl, [u.uno]
  2339 00005105 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2340 00005107 81C3[02640000]      <1> 	add	ebx, p.ppid-2
  2341 0000510D 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2342 00005110 BE[E4630000]        <1> 	mov	esi, p.pid
  2343 00005115 29C9                <1> 	sub	ecx, ecx
  2344 00005117 B110                <1> 	mov	cl, nproc ; 16  
  2345                              <1> sysumnt_2:	
  2346 00005119 66AD                <1> 	lodsw
  2347 0000511B 6639D0              <1> 	cmp	ax, dx
  2348 0000511E 7402                <1> 	je	short sysumnt_3
  2349 00005120 E2F7                <1> 	loop	sysumnt_2
  2350                              <1> sysumnt_3:
  2351 00005122 31C0                <1> 	xor	eax, eax
  2352 00005124 81EE[E4630000]      <1> 	sub	esi, p.pid
  2353 0000512A D1E6                <1> 	shl	esi, 1
  2354 0000512C 8B9E[50640000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2355                              <1> 	; ebx points to user (u) structure in upage
  2356 00005132 668B15[B2660000]    <1> 	mov	dx, [mnti]
  2357                              <1> 	;mov	[u.cdir], dx
  2358                              <1> 	;mov	[u.cdrv], al ; 0
  2359 00005139 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2360 0000513D 88434C              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2361                              <1> 	;;;
  2362                              <1> sysumnt_4: 
  2363 00005140 A2[AF660000]        <1> 	mov	[mdev], al ; 0
  2364                              <1> 	     	; clr mntd / no, clear these
  2365 00005145 66A3[B2660000]      <1>    	mov	[mnti], ax ; 0
  2366                              <1>         	; clr mnti
  2367                              <1> 
  2368                              <1> 	;; 15/05/2022
  2369                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2370                              <1> 	;mov	ax, dx  ; [u.cdir]
  2371                              <1> 	;call	iget		
  2372                              <1> 
  2373 0000514B E9D8E0FFFF          <1>         jmp	sysret
  2374                              <1> 		; br sysreta / return
  2375                              <1> 
  2376                              <1> sysmnt_err0:
  2377 00005150 C705[17670000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2377 00005158 0000                <1>
  2378 0000515A E9A9E0FFFF          <1> 	jmp	error
  2379                              <1> 
  2380                              <1> getspl: ; / get device number from a special file name
  2381 0000515F E8A5EFFFFF          <1> 	call	namei
  2382                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2383                              <1> 		       ; ax = 0 -> file not found 	
  2384                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2385                              <1> 	; 04/02/2022
  2386 00005164 7305                <1> 	jnc	short getspl_0
  2387 00005166 E9C5FEFFFF          <1> 	jmp	sysmnt_err2
  2388                              <1> getspl_0:
  2389                              <1> 	;jz	error
  2390                              <1> 	;jc	error
  2391                              <1> 		; jsr r0,namei / get the i-number of the special file
  2392                              <1>                 ; br errora / no such file
  2393 0000516B 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2394                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2395                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2396 0000516F 72DF                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2397                              <1> 	;jc	error
  2398                              <1> 		; ble errora / less than 0?  yes, error
  2399 00005171 6683F805            <1>         cmp	ax, 5 ;
  2400                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2401                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2402                              <1> 	;;ja	error
  2403                              <1>         ;	; bgt errora / yes, error
  2404                              <1>         ; 04/02/2022
  2405 00005175 7600                <1> 	jna	short getspl_retn
  2406                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2407                              <1> ;iopen_retn:
  2408                              <1> ;	retn
  2409                              <1> 		; rts r0 / return with device number in r1
  2410                              <1> ;sysmnt_err0:
  2411                              <1> ;	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2412                              <1> ;	jmp	error
  2413                              <1> 
  2414                              <1> getspl_retn:
  2415                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2416                              <1> 	; 04/02/2022
  2417                              <1> iopen_retn:
  2418 00005177 C3                  <1> 	retn
  2419                              <1> 
  2420                              <1> iopen:
  2421                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2422                              <1> 	;		(Printer initialization)
  2423                              <1> 	; 04/02/2022
  2424                              <1> 	; 19/05/2015
  2425                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2426                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2427                              <1> 	;
  2428                              <1> 	; open file whose i-number is in r1
  2429                              <1> 	; 
  2430                              <1> 	; INPUTS ->
  2431                              <1> 	;    r1 - inode number
  2432                              <1> 	; OUTPUTS ->
  2433                              <1> 	;    file's inode in core	
  2434                              <1> 	;    r1 - inode number (positive)
  2435                              <1> 	;
  2436                              <1> 	; ((AX = R1))
  2437                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2438                              <1> 	;        
  2439                              <1> ; / open file whose i-number is in r1
  2440 00005178 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2441                              <1> 		; tst r1 / write or read access?
  2442 0000517B 7568                <1>         jnz	short iopen_2
  2443                              <1> 		; blt 2f / write, go to 2f
  2444 0000517D B202                <1> 	mov	dl, 2 ; read access
  2445 0000517F E86EF8FFFF          <1> 	call	access
  2446                              <1>         	; jsr r0,access; 2 
  2447                              <1> 	; / get inode into core with read access
  2448                              <1> 	; DL=2
  2449                              <1> iopen_0:
  2450 00005184 6683F828            <1>         cmp	ax, 40
  2451                              <1> 		; cmp r1,$40. / is it a special file
  2452 00005188 77ED                <1>         ja	short iopen_retn
  2453                              <1> 		; bgt 3f / no. 3f
  2454                              <1> 	; 04/02/2022
  2455 0000518A 50                  <1> 	push	eax
  2456                              <1> 	;push	ax
  2457                              <1> 		; mov r1,-(sp) / yes, figure out
  2458 0000518B 0FB6D8              <1> 	movzx	ebx, al
  2459 0000518E C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2460                              <1> 	;shl	bx, 2
  2461                              <1> 		; asl r1
  2462 00005191 81C3[95510000]      <1>         add     ebx, iopen_1 - 4
  2463 00005197 FF23                <1> 	jmp	dword [ebx]
  2464                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2465                              <1> iopen_1: ; 1:
  2466 00005199 [FD510000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2467                              <1>  		 ;otty / tty ; r1=2
  2468                              <1>         	 ;oppt / ppt ; r1=4
  2469 0000519D [B5520000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2470                              <1> 		 ;sret / mem ; r1=6
  2471                              <1> 		 ;sret / rf0
  2472                              <1>         	 ;sret / rk0
  2473                              <1>         	 ;sret / tap0
  2474                              <1>         	 ;sret / tap1
  2475                              <1>         	 ;sret / tap2
  2476                              <1>         	 ;sret / tap3
  2477                              <1>         	 ;sret / tap4
  2478                              <1>         	 ;sret / tap5
  2479                              <1>         	 ;sret / tap6
  2480                              <1>         	 ;sret / tap7
  2481 000051A1 [B5520000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2482 000051A5 [B5520000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2483 000051A9 [B5520000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2484 000051AD [B5520000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2485 000051B1 [B5520000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2486 000051B5 [B5520000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2487                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2488                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2489                              <1> 	; 13/06/2022 - (lpt_init)
  2490 000051B9 [81530000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2491 000051BD [0E520000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2492                              <1> 		 ;ocvt / tty0
  2493 000051C1 [0E520000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2494                              <1> 		 ;ocvt / tty1
  2495 000051C5 [0E520000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2496                              <1> 		 ;ocvt / tty2
  2497 000051C9 [0E520000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2498                              <1> 		 ;ocvt / tty3
  2499 000051CD [0E520000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2500                              <1> 		 ;ocvt / tty4
  2501 000051D1 [0E520000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2502                              <1> 		 ;ocvt / tty5
  2503 000051D5 [0E520000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2504                              <1> 		 ;ocvt / tty6
  2505 000051D9 [0E520000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2506                              <1> 		 ;ocvt / tty7
  2507 000051DD [0E520000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2508                              <1> 		 ;error / crd
  2509 000051E1 [0E520000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2510                              <1> 
  2511                              <1> iopen_2: ; 2: / check open write access
  2512 000051E5 66F7D8              <1> 	neg	ax
  2513                              <1> 		; neg r1 / make inode number positive
  2514 000051E8 B201                <1> 	mov	dl, 1 ; write access
  2515 000051EA E803F8FFFF          <1> 	call	access
  2516                              <1> 		; jsr r0,access; 1 / get inode in core
  2517                              <1> 	; DL=1
  2518                              <1> 	; 04/02/2022
  2519 000051EF F605[C5630000]40    <1> 	test	byte [i.flgs+1], 40h
  2520                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2521                              <1>  		; bit $40000,i.flgs / is it a directory?
  2522 000051F6 748C                <1> 	jz	short iopen_0
  2523                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2524                              <1> 	;jmp	error ; permission denied !
  2525 000051F8 E953FFFFFF          <1> 	jmp	sysmnt_err0
  2526                              <1> 	;;jnz	error		
  2527                              <1>        		; bne 2f / yes, transfer (error)
  2528                              <1>         ;;jmp	short iopen_0
  2529                              <1> 	;cmp	ax, 40
  2530                              <1> 		; cmp r1,$40. / no, is it a special file?
  2531                              <1>         ;ja	short iopen_2
  2532                              <1> 		; bgt 3f / no, return
  2533                              <1> 	;push	ax
  2534                              <1> 		; mov r1,-(sp) / yes
  2535                              <1> 	;movzx	ebx, al
  2536                              <1> 	;shl	bx, 1
  2537                              <1> 		; asl r1
  2538                              <1> 	;add	ebx, ipen_3 - 2
  2539                              <1> 	;jmp	dword [ebx]
  2540                              <1> 		; jmp *1f-2(r1) / figure out 
  2541                              <1> 			; / which special file it is and transfer
  2542                              <1> ;iopen_3: ; 1:
  2543                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2544                              <1>  		 ;otty / tty ; r1=2
  2545                              <1>         	 ;leadr / ppt ; r1=4
  2546                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2547                              <1> 		 ;sret / mem ; r1=6
  2548                              <1> 		 ;sret / rf0
  2549                              <1>         	 ;sret / rk0
  2550                              <1>         	 ;sret / tap0
  2551                              <1>         	 ;sret / tap1
  2552                              <1>         	 ;sret / tap2
  2553                              <1>         	 ;sret / tap3
  2554                              <1>         	 ;sret / tap4
  2555                              <1>         	 ;sret / tap5
  2556                              <1>         	 ;sret / tap6
  2557                              <1>         	 ;sret / tap7
  2558                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2559                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2560                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2561                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2562                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2563                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2564                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2565                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2566                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2567                              <1> 		 ;ocvt / tty0
  2568                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2569                              <1> 		 ;ocvt / tty1
  2570                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2571                              <1> 		 ;ocvt / tty2
  2572                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2573                              <1> 		 ;ocvt / tty3
  2574                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2575                              <1> 		 ;ocvt / tty4
  2576                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2577                              <1> 		 ;ocvt / tty5
  2578                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2579                              <1> 		 ;ocvt / tty6
  2580                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2581                              <1> 		 ;ocvt / tty7
  2582                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2583                              <1> 		 ;/ ejec / lpr
  2584                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2585                              <1> 
  2586                              <1> otty: ;/ open console tty for reading or writing
  2587                              <1> 	; 03/03/2022
  2588                              <1> 	; 02/03/2022
  2589                              <1> 	; 27/02/2022
  2590                              <1> 	; 23/02/2022
  2591                              <1> 	; 22/02/2022
  2592                              <1> 	; 04/02/2022
  2593                              <1> 	; 16/11/2015
  2594                              <1> 	; 12/11/2015
  2595                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2596                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2597                              <1> 	; 16/07/2013
  2598                              <1> 	; Retro UNIX 8086 v1 modification:
  2599                              <1> 	;  If a tty is open for read or write by
  2600                              <1> 	;     a process (u.uno), only same process can open
  2601                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2602                              <1> 	;
  2603                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2604                              <1> 	;
  2605 000051FD 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2606 00005204 8A83[23640000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2607                              <1> 	; 13/01/2014
  2608                              <1> 	;jmp	short ottyp
  2609                              <1> 	; 23/02/2022
  2610 0000520A 88C4                <1> 	mov	ah, al
  2611 0000520C EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2612                              <1> ocvt:
  2613 0000520E 2C0A                <1> 	sub	al, 10
  2614                              <1> 	; 04/02/2022
  2615 00005210 31DB                <1> 	xor	ebx, ebx
  2616                              <1> ottyp:
  2617                              <1> 	; 23/02/2022
  2618 00005212 B4FF                <1> 	mov	ah, 0FFh
  2619                              <1> ottypc:
  2620                              <1> 	; 03/03/2022
  2621                              <1> 	; 23/02/2022
  2622                              <1> 	; 22/02/2022
  2623                              <1> 	; 12/02/2022
  2624                              <1> 	; 04/02/2022
  2625                              <1> 	; 16/11/2015
  2626                              <1> 	; 12/11/2015
  2627                              <1> 	; 18/05/2015 (32 bit modifications)
  2628                              <1> 	; 06/12/2013 - 13/07/2014
  2629 00005214 88C6                <1> 	mov	dh, al ; tty number
  2630                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2631                              <1> 	; 04/02/2022
  2632 00005216 88C3                <1> 	mov	bl, al
  2633 00005218 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2634                              <1> 	; 26/01/2014	
  2635 0000521A 81C3[54630000]      <1> 	add 	ebx, ttyl
  2636 00005220 668B0B              <1> 	mov 	cx, [ebx]
  2637                              <1> 		   ; CL = lock value (0 or process number)
  2638                              <1> 		   ; CH = open count 
  2639 00005223 20C9                <1> 	and 	cl, cl
  2640                              <1> 	; 13/01/2014
  2641                              <1> 	;jz 	short otty_ret
  2642                              <1> 	; 04/02/2022
  2643 00005225 7447                <1> 	jz 	short ottys_0
  2644                              <1> 	;
  2645                              <1> 	; 16/11/2015
  2646 00005227 3A0D[11670000]      <1> 	cmp 	cl, [u.uno]
  2647 0000522D 746E                <1> 	je	short ottys_3
  2648                              <1> 	;
  2649                              <1> 	; 23/02/2022
  2650                              <1> 	; (is it the console tty of the current process?)
  2651                              <1> 	; ((fast check/permit for console tty open function))
  2652 0000522F 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2653 00005231 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2654                              <1> 	;
  2655                              <1> 	; 22/02/2022
  2656                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2657                              <1> 	;shl 	bl, 1
  2658                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2659                              <1> 	;;movzx ebx, byte [u.uno]
  2660                              <1> 	;mov	bl, [u.uno]
  2661                              <1> 	;shl 	bl, 1
  2662                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2663                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2664                              <1> 	; 22/02/2022 (BugFix) ; *
  2665 00005233 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2666 00005236 D1E6                <1> 	shl 	esi, 1
  2667 00005238 668B86[E2630000]    <1> 	mov 	ax, [esi+p.pid-2]
  2668 0000523F 96                  <1> 	xchg	esi, eax
  2669 00005240 A0[11670000]        <1> 	mov	al, [u.uno]
  2670 00005245 D0E0                <1> 	shl 	al, 1
  2671 00005247 663BB0[02640000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2672 0000524E 744D                <1> 	je 	short ottys_3 ; *
  2673                              <1> 	; 23/02/2022
  2674                              <1> 	; check console tty of the process
  2675                              <1> 	; (open permission must be given if the -requested- tty is
  2676                              <1> 	;  console tty of current process)
  2677 00005250 D0E8                <1> 	shr	al, 1
  2678 00005252 38B0[23640000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2679 00005258 7443                <1> 	je 	short ottys_3
  2680                              <1> 	;
  2681                              <1> 	; the tty is locked by another process
  2682                              <1> 	; except the parent process (p.ppid)
  2683                              <1>         ;
  2684                              <1> 	; 09/02/2022
  2685                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2686                              <1> 	;		; permission denied ! error
  2687                              <1> otty_err: ; 13/01/2014
  2688                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2689                              <1> 	;;jnz	error
  2690                              <1> 	; 04/02/2022
  2691                              <1> 	;jz	short otty_stc_retn
  2692                              <1> 	;jmp	error
  2693                              <1> 	; 12/02/2022
  2694 0000525A 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2695 0000525D 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2696                              <1> 	; iopen (dl=1 or dl=2)
  2697 0000525F C705[17670000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2697 00005267 0000                <1>
  2698                              <1> 			; permission denied ! error
  2699 00005269 E99ADFFFFF          <1> 	jmp	error
  2700                              <1> ;otty_stc_retn:
  2701                              <1> 	;stc
  2702                              <1> 	;retn
  2703                              <1> ottys_0:
  2704                              <1> 	; 04/02/2022
  2705                              <1> otty_ret: 
  2706                              <1> 	; 13/01/2014
  2707 0000526E 80FE07              <1> 	cmp 	dh, 7
  2708 00005271 7624                <1> 	jna	short ottys_2
  2709                              <1> 	; 16/11/2015
  2710                              <1> com_port_check:
  2711 00005273 BE[72630000]        <1> 	mov	esi, com1p
  2712 00005278 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2713 0000527B 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2714 0000527D 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2715                              <1> ottys_1:
  2716                              <1> 	; 12/11/2015
  2717 0000527E 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2718 00005281 7714                <1> 	ja	short com_port_ready
  2719                              <1> 	;
  2720                              <1> 	; 12/02/2022
  2721 00005283 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2722 00005286 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2723 00005288 C705[17670000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2723 00005290 0000                <1>
  2724                              <1> 			   ; device not ready ! error
  2725                              <1> 	;jmp	short otty_err
  2726 00005292 E971DFFFFF          <1> 	jmp	error
  2727                              <1> com_port_ready:
  2728                              <1> ottys_2:
  2729                              <1> 	; 02/03/2022
  2730                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2731                              <1> 	;jnz	short ottys_3
  2732 00005297 8A0D[11670000]      <1> 	mov	cl, [u.uno]
  2733                              <1> ottys_3:
  2734 0000529D FEC5                <1> 	inc 	ch
  2735 0000529F 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2736                              <1> 	; 06/12/2013
  2737 000052A2 FEC6                <1> 	inc	dh	; tty number + 1
  2738 000052A4 BB[F8660000]        <1> 	mov	ebx, u.ttyp
  2739                              <1> 	; 13/01/2014
  2740 000052A9 F6C202              <1> 	test	dl, 2	; open for read sign
  2741 000052AC 7501                <1> 	jnz	short ottys_4
  2742 000052AE 43                  <1> 	inc	ebx
  2743                              <1> ottys_4:
  2744                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2745 000052AF 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2746                              <1> 	; 27/02/2022
  2747 000052B1 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2748 000052B3 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2749                              <1> sret:
  2750                              <1> 	;pop 	ax
  2751                              <1> 	; 04/02/2022
  2752 000052B5 58                  <1> 	pop	eax
  2753                              <1> otty_retn:	; 12/02/2022
  2754                              <1> iclose_retn:	
  2755 000052B6 C3                  <1> 	retn
  2756                              <1> 
  2757                              <1> 	;
  2758                              <1> 	; Original UNIX v1 'otty' routine:
  2759                              <1> 	;	
  2760                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2761                              <1>         ;                 / reader status reg
  2762                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2763                              <1>         ;                 / punch status reg
  2764                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2765                              <1>         ;                          / console tty buffer
  2766                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2767                              <1>         ;            / console tty
  2768                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2769                              <1>         ;             / buffer header
  2770                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2771                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2772                              <1>         ;                 / tty
  2773                              <1>         ;br     sret / ?
  2774                              <1> ;sret:
  2775                              <1> 		; clr *$ps / set processor priority to zero
  2776                              <1> ;	pop	ax
  2777                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2778                              <1> ;3:
  2779                              <1> ;	retn
  2780                              <1>         	; rts r0
  2781                              <1> 	
  2782                              <1> ;ocvt:	; < open tty >
  2783                              <1> 	; 13/01/2014
  2784                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2785                              <1> 	; 24/09/2013 consistency check -> ok
  2786                              <1> 	; 16/09/2013
  2787                              <1> 	; 03/09/2013
  2788                              <1> 	; 27/08/2013
  2789                              <1> 	; 16/08/2013
  2790                              <1> 	; 16/07/2013
  2791                              <1> 	; 27/05/2013
  2792                              <1> 	; 21/05/2013
  2793                              <1> 	;
  2794                              <1> 	; Retro UNIX 8086 v1 modification !
  2795                              <1> 	; 
  2796                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2797                              <1> 	;		(exactly different than this one)
  2798                              <1> 	;	was in 'u9.s' file.
  2799                              <1> 	;
  2800                              <1> 	; 16/07/2013
  2801                              <1> 	; Retro UNIX 8086 v1 modification:
  2802                              <1> 	;  If a tty is open for read or write by
  2803                              <1> 	;     a process (u.uno), only same process can open
  2804                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2805                              <1> 	;
  2806                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2807                              <1> 
  2808                              <1> 	; 16/09/2013
  2809                              <1> 	; sub 	al, 10
  2810                              <1> 	
  2811                              <1> 	; 06/12/2013
  2812                              <1> 	;cmp	al, 7
  2813                              <1>         ;jna     short ottyp
  2814                              <1> 	; 13/01/2014
  2815                              <1> 	;jmp	short ottyp
  2816                              <1> 
  2817                              <1> 
  2818                              <1> ;oppt: / open paper tape for reading or writing
  2819                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2820                              <1> ;        tstb   pptiflg / is file already open
  2821                              <1> ;        bne    2f / yes, branch
  2822                              <1> ;1:
  2823                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2824                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2825                              <1> ;               br .+4 / for paper tape input and place in free list
  2826                              <1> ;        br     1b
  2827                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2828                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2829                              <1> ;        br     sret
  2830                              <1> ;2:
  2831                              <1> ;        jmp    error / file already open
  2832                              <1> 
  2833                              <1> iclose: 
  2834                              <1> 	; 04/02/2022
  2835                              <1> 	; 19/05/2015
  2836                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2837                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2838                              <1> 	;
  2839                              <1> 	; close file whose i-number is in r1
  2840                              <1> 	; 
  2841                              <1> 	; INPUTS ->
  2842                              <1> 	;    r1 - inode number
  2843                              <1> 	; OUTPUTS ->
  2844                              <1> 	;    file's inode in core	
  2845                              <1> 	;    r1 - inode number (positive)
  2846                              <1> 	;
  2847                              <1> 	; ((AX = R1))
  2848                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2849                              <1> 	;        
  2850                              <1> ;/ close file whose i-number is in r1
  2851 000052B7 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2852 000052B9 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2853                              <1> 		; tst r1 / test i-number
  2854                              <1>         ;jnz	short iclose_2
  2855                              <1> 		; blt 2f / if neg., branch
  2856 000052BC 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2857                              <1> 	; 16/07/2013 
  2858 000052BE 66F7D8              <1> 	neg	ax ; make it positive
  2859                              <1> 	; 12/01/2014
  2860 000052C1 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2861                              <1> iclose_0:
  2862 000052C3 6683F828            <1> 	cmp	ax, 40
  2863                              <1> 		; cmp r1,$40. / is it a special file
  2864 000052C7 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2865                              <1> 		; bgt 3b / no, return
  2866                              <1> 	; 12/01/2014
  2867                              <1> 	; DL=2 -> special file was opened for reading
  2868                              <1> 	; DL=1 -> special file was opened for writing
  2869                              <1> 	; 04/02/2022
  2870 000052C9 50                  <1> 	push	eax
  2871                              <1> 	;push	ax
  2872                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2873 000052CA 0FB6D8              <1> 	movzx	ebx, al
  2874                              <1> 	; 04/02/2022
  2875 000052CD C0E302              <1> 	shl	bl, 2
  2876                              <1> 	;shl	bx, 2
  2877                              <1> 		; asl r1
  2878 000052D0 81C3[D4520000]      <1> 	add	ebx, iclose_1 - 4
  2879 000052D6 FF23                <1> 	jmp	dword [ebx]
  2880                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2881                              <1> iclose_1 :
  2882 000052D8 [24530000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2883 000052DC [7F530000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2884 000052E0 [7F530000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2885 000052E4 [7F530000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2886 000052E8 [7F530000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2887 000052EC [7F530000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2888 000052F0 [7F530000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2889 000052F4 [7F530000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2890 000052F8 [7F530000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2891                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2892                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2893 000052FC [33530000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2894 00005300 [33530000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2895 00005304 [33530000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2896 00005308 [33530000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2897 0000530C [33530000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2898 00005310 [33530000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2899 00005314 [33530000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2900 00005318 [33530000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2901 0000531C [33530000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2902 00005320 [33530000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2903                              <1> 
  2904                              <1> 	; 1:
  2905                              <1> 	;        ctty   / tty
  2906                              <1> 	;        cppt   / ppt
  2907                              <1> 	;        sret   / mem
  2908                              <1> 	;        sret   / rf0
  2909                              <1> 	;        sret   / rk0
  2910                              <1> 	;        sret   / tap0
  2911                              <1> 	;        sret   / tap1
  2912                              <1> 	;        sret   / tap2
  2913                              <1> 	;        sret   / tap3
  2914                              <1> 	;        sret   / tap4
  2915                              <1> 	;        sret   / tap5
  2916                              <1> 	;        sret   / tap6
  2917                              <1> 	;        sret   / tap7
  2918                              <1> 	;        ccvt   / tty0
  2919                              <1> 	;        ccvt   / tty1
  2920                              <1> 	;        ccvt   / tty2
  2921                              <1> 	;        ccvt   / tty3
  2922                              <1> 	;        ccvt   / tty4
  2923                              <1> 	;        ccvt   / tty5
  2924                              <1> 	;        ccvt   / tty6
  2925                              <1> 	;        ccvt   / tty7
  2926                              <1> 	;        error / crd
  2927                              <1> 
  2928                              <1> ;iclose_2: ; 2: / negative i-number
  2929                              <1> 	;neg	ax
  2930                              <1> 		;neg r1 / make it positive
  2931                              <1> 	;cmp	ax, 40
  2932                              <1> 		;cmp r1,$40. / is it a special file?
  2933                              <1>         ;ja	short @b
  2934                              <1> 		;bgt    3b / no. return
  2935                              <1> 	;push	ax
  2936                              <1> 		;mov r1,-(sp)
  2937                              <1> 	;movzx	ebx, al
  2938                              <1> 	;shl	bx, 1
  2939                              <1> 		;asl r1 / yes. compute jump address and transfer
  2940                              <1> 	;add	ebx, iclose_3 - 2
  2941                              <1> 	;jmp	dword [ebx]
  2942                              <1> 		;jmp *1f-2(r1) / figure out 
  2943                              <1> ;iclose_3:
  2944                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2945                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2946                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2947                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2948                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2949                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2950                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2951                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2952                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2953                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2954                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2955                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2956                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2957                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2958                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2959                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2960                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2961                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2962                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2963                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2964                              <1> 	
  2965                              <1> 	;1:
  2966                              <1> 	;      	ctty   / tty
  2967                              <1> 	;       leadr  / ppt
  2968                              <1> 	;       sret   / mem
  2969                              <1> 	;       sret   / rf0
  2970                              <1> 	;       sret   / rk0
  2971                              <1> 	;       sret   / tap0
  2972                              <1> 	;       sret   / tap1
  2973                              <1> 	;       sret   / tap2
  2974                              <1> 	;       sret   / tap3
  2975                              <1> 	;       sret   / tap4
  2976                              <1> 	;       sret   / tap5
  2977                              <1> 	;       sret   / tap6
  2978                              <1> 	;       sret   / tap7
  2979                              <1> 	;       ccvt   / tty0
  2980                              <1> 	;       ccvt   / tty1
  2981                              <1> 	;       ccvt   / tty2
  2982                              <1> 	;       ccvt   / tty3
  2983                              <1> 	;       ccvt   / tty4
  2984                              <1> 	;       ccvt   / tty5
  2985                              <1> 	;       ccvt   / tty6
  2986                              <1> 	;       ccvt   / tty7
  2987                              <1> 	;/       ejec / lpr
  2988                              <1> 
  2989                              <1> ctty: ; / close console tty
  2990                              <1> 	; 25/02/2022
  2991                              <1> 	; 12/02/2022
  2992                              <1> 	; 05/02/2022
  2993                              <1> 	; 04/02/2022
  2994                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2995                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2996                              <1> 	;
  2997                              <1> 	; Retro UNIX 8086 v1 modification !
  2998                              <1> 	; (DL = 2 -> it is open for reading)
  2999                              <1> 	; (DL = 1 -> it is open for writing)
  3000                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3001                              <1> 	;
  3002                              <1> 	; 06/12/2013
  3003 00005324 0FB61D[11670000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3004 0000532B 8A83[23640000]      <1>         mov     al, [ebx+p.ttyc-1]
  3005                              <1> 	; 13/01/2014
  3006                              <1> 	;jmp	short cttyp
  3007                              <1> 	; 05/02/2022
  3008 00005331 EB04                <1> 	jmp	short ctty_0
  3009                              <1> ccvt:
  3010 00005333 2C0A                <1> 	sub 	al, 10
  3011                              <1> cttyp:	; (call from sysstty)
  3012                              <1> 	; 08/01/2022
  3013 00005335 31DB                <1> 	xor	ebx, ebx
  3014                              <1> ctty_0:	
  3015                              <1> 	; 18/05/2015 (32 bit modifications)
  3016                              <1> 	; 16/08/2013 - 26/01/2014
  3017                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3018                              <1> 	; 04/02/2022
  3019 00005337 88C3                <1> 	mov	bl, al
  3020 00005339 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3021                              <1> 	; 26/01/2014
  3022 0000533B 81C3[54630000]      <1> 	add 	ebx, ttyl
  3023 00005341 88C6                <1> 	mov 	dh, al ; tty number
  3024 00005343 668B03              <1> 	mov 	ax, [ebx]
  3025                              <1> 		   ; AL = lock value (0 or process number)
  3026                              <1> 		   ; AH = open count 
  3027 00005346 20E4                <1> 	and 	ah, ah
  3028 00005348 7514                <1> 	jnz	short ctty_ret
  3029                              <1>   	; 12/02/2022
  3030 0000534A 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3031 0000534D 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3032                              <1> 	; iclose (dl=1 or dl=2)
  3033 0000534F C705[17670000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3033 00005357 0000                <1>
  3034                              <1> 			; device not open ! error
  3035                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3036 00005359 E9AADEFFFF          <1> 	jmp	error
  3037                              <1> 	; 26/01/2014
  3038                              <1> ctty_ret:
  3039 0000535E FECC                <1> 	dec 	ah ; decrease open count
  3040 00005360 7502                <1> 	jnz	short ctty_1
  3041 00005362 30C0                <1> 	xor	al, al ; unlock/free tty
  3042                              <1> ctty_1:
  3043 00005364 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3044                              <1> 	;
  3045 00005367 BB[F8660000]        <1> 	mov	ebx, u.ttyp
  3046                              <1> 	;test	dl, 1 ; open for write sign
  3047                              <1> 	;jz	short ctty_2
  3048                              <1> 	; 25/02/2022
  3049 0000536C F6C202              <1> 	test	dl, 2 ; open for read sign
  3050 0000536F 7501                <1> 	jnz	short ctty_2
  3051 00005371 43                  <1> 	inc	ebx
  3052                              <1> ctty_2:
  3053 00005372 FEC6                <1> 	inc	dh ; tty number + 1
  3054 00005374 3A33                <1> 	cmp	dh, [ebx]
  3055                              <1> 	;jne	short cret
  3056 00005376 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  3057                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3058 00005378 C60300              <1> 	mov	byte [ebx], 0
  3059                              <1> ctty_3:
  3060                              <1> 	; 12/02/2022
  3061 0000537B 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3062 0000537D 7401                <1> 	jz	short ctty_4
  3063                              <1> cret:
  3064                              <1> 	;pop	ax
  3065                              <1> 	; 05/02/2022
  3066 0000537F 58                  <1> 	pop	eax
  3067                              <1> ctty_stc_retn:	; 12/02/2022
  3068                              <1> ctty_4:
  3069 00005380 C3                  <1> 	retn
  3070                              <1> 
  3071                              <1> ;ctty_err: ; 13/01/2014
  3072                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3073                              <1> ;	jnz	error
  3074                              <1> ;	stc
  3075                              <1> ;	retn
  3076                              <1> 
  3077                              <1> 	; Original UNIX v1 'ctty' routine:
  3078                              <1> 	;	
  3079                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3080                              <1> 	;		;/ point r5 to the console tty buffer
  3081                              <1>         ;decb   (r5) / dec number of processes using console tty
  3082                              <1>         ;br     sret / return via sret
  3083                              <1> 
  3084                              <1> ;ccvt:	; < close tty >
  3085                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3086                              <1> 	;
  3087                              <1> 	; Retro UNIX 8086 v1 modification !
  3088                              <1> 	; 
  3089                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3090                              <1> 	;		(exactly different than this one)
  3091                              <1> 	;	was in 'u9.s' file.
  3092                              <1> 	;
  3093                              <1> 	; DL = 2 -> it is open for reading
  3094                              <1> 	; DL = 1 -> it is open for writing
  3095                              <1> 	;
  3096                              <1> 	; 17/09/2013
  3097                              <1> 	;sub 	al, 10
  3098                              <1> 	;cmp	al, 7
  3099                              <1> 	;jna	short cttyp
  3100                              <1> 	; 13/01/2014
  3101                              <1> 	;jmp	short cttyp
  3102                              <1> 
  3103                              <1> ;cppt: / close paper tape
  3104                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3105                              <1> ;1:
  3106                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3107                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3108                              <1> ;                          / and assign to free list
  3109                              <1> ;               br sret
  3110                              <1> ;        br     1b
  3111                              <1> 
  3112                              <1> ;ejec:	
  3113                              <1> ;	jmp	error
  3114                              <1> ;/ejec:
  3115                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3116                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3117                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3118                              <1> ;/       br     sret / return to caller via 'sret'
  3119                              <1> 
  3120                              <1> ejec:
  3121                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kewrnel v0.2.0.20)
  3122                              <1> 	;	     - Printer Initialization
  3123                              <1> lpt_init:	
  3124                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3125                              <1> 	;
  3126                              <1> 	; Default printer port: 378h ; LPT1
  3127                              <1> 	
  3128 00005381 B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3129                              <1> 	;call	int17h
  3130 00005383 E8C3FAFFFF          <1> 	call	PRNOP
  3131 00005388 7414                <1> 	jz	short lpt_init_ok
  3132                              <1> 	
  3133                              <1> 	; replace error code with 'device not ready' error
  3134                              <1> 	; (this may be better for 'sysopen')
  3135 0000538A B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3136 0000538F A3[17670000]        <1> 	mov	[u.error], eax
  3137                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3138 00005394 A3[C8660000]        <1> 	mov	[u.r0], eax
  3139 00005399 E96ADEFFFF          <1> 	jmp	error ; (better)	
  3140                              <1> 	
  3141                              <1> lpt_init_ok:
  3142                              <1> 	;jmp	short cret
  3143 0000539E 58                  <1> 	pop	eax    ; inode number
  3144 0000539F C3                  <1> 	retn
  3145                              <1> 	
  2056                                  %include 'u8.s'        ; 11/06/2015
  2057                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - SYS8.INC
  2058                              <1> ; Last Modification: 12/07/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 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2069                              <1> ;
  2070                              <1> ; ****************************************************************************
  2071                              <1> ; 24/10/2015
  2072                              <1> 
  2073                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2074                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2075                              <1> ;; Word 1, byte 0 = device id
  2076                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2077                              <1> ;;          bit 9 = write bit
  2078                              <1> ;;	    bit 10 = read bit	  
  2079                              <1> ;;	    bit 12 = waiting to write bit	
  2080                              <1> ;;	    bit 13 = waiting to read bit
  2081                              <1> ;;	    bit 15 = inhibit bit
  2082                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2083                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2084                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2085                              <1> ;;
  2086                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2087                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2088                              <1> ;;
  2089                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2090                              <1> ;; Word 1, Byte 0 = device id
  2091                              <1> ;; Word 1, Byte 1 = (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 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2098                              <1> ;;
  2099                              <1> ;; Original UNIX v1 ->
  2100                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2101                              <1> ;; Original UNIX v1 -> 
  2102                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2103                              <1> ;;
  2104                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2105                              <1> ;;
  2106                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2107                              <1> ;;          0 = fd0
  2108                              <1> ;;	    1 = fd1
  2109                              <1> ;;	    2 = hd0
  2110                              <1> ;;	    3 = hd1
  2111                              <1> ;;	    4 = hd2
  2112                              <1> ;;	    5 = hd3
  2113                              <1> 
  2114                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2115                              <1> 
  2116                              <1> 	; 04/02/2022
  2117                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2118                              <1> 	; 26/04/2013
  2119                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2120                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2121                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2122                              <1> 
  2123                              <1> 	; 04/02/2022
  2124                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2125                              <1> 	; 26/04/2013
  2126                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2127                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2128                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2129                              <1> 
  2130                              <1> bread: 
  2131                              <1> 	; 12/02/2022
  2132                              <1> 	; 04/02/2022
  2133                              <1> 	; 14/07/2015
  2134                              <1> 	; 10/07/2015
  2135                              <1> 	; 09/06/2015
  2136                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2137                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2138                              <1> 	;	
  2139                              <1> 	; / read a block from a block structured device
  2140                              <1> 	;
  2141                              <1> 	; INPUTS ->
  2142                              <1> 	;    [u.fofp] points to the block number
  2143                              <1> 	;    CX = maximum block number allowed on device
  2144                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2145                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2146                              <1> 	;    [u.count]	number of bytes to read in
  2147                              <1> 	; OUTPUTS ->
  2148                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2149                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2150                              <1> 	;
  2151                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2152                              <1> 	;
  2153                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2154                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2155                              <1> 	;	is increased by 1. For example: If user/program request 
  2156                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2157                              <1> 	;  	the next block number just as 512 byte reading is done.
  2158                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2159                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2160                              <1> 	;       enough to keep byte position/offset of the disk), this
  2161                              <1> 	;	defect will not be corrected, user/program must request
  2162                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2163                              <1> 	;       for achieving correct result. In future version(s), 
  2164                              <1> 	;	this defect will be corrected by using different 
  2165                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2166                              <1> 
  2167                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2168                              <1> 			       ; / (only works on tape)
  2169                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2170                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2171                              <1> ;1:
  2172                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2173                              <1> 			    ; / maximum block # allowed on device
  2174                              <1> 		; jnb short @f
  2175                              <1> 		; bhis	1f / yes, 1f (error)
  2176                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2177                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2178                              <1> 		; mov (sp)+,r1 / return block # to r1
  2179                              <1> 		; inc r1 / bump block # to next consecutive block
  2180                              <1> 		; dec (sp) / "2-1-cold" on stack
  2181                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2182                              <1> ;1:
  2183                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2184                              <1> 	;push	ecx ; **
  2185                              <1> 	;26/04/2013
  2186                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2187 000053A0 2C03                <1> 	sub	al, 3
  2188                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2189 000053A2 A2[2A670000]        <1> 	mov	[u.brwdev], al
  2190                              <1> 	; 09/06/2015
  2191                              <1> 	;movzx	ebx, al
  2192                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2193                              <1> 	; 04/02/2022 (BugFix)
  2194 000053A7 C0E002              <1> 	shl	al, 2 ; * 4
  2195 000053AA 8B88[325E0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2196                              <1> bread_0:
  2197 000053B0 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2198                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2199                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2200 000053B1 8B1D[D8660000]      <1> 	mov	ebx, [u.fofp]
  2201 000053B7 8B03                <1> 	mov	eax, [ebx]
  2202 000053B9 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2203                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2204                              <1> 			       ; / block #
  2205 000053BC 39C8                <1> 	cmp	eax, ecx
  2206                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2207                              <1>        	                     ; / block number allowed
  2208                              <1> 	;jnb	error 	     ; 18/04/2013
  2209                              <1> 		; bhis error10 / yes, error
  2210                              <1> 	; 12/02/2022
  2211                              <1> 	;jb	short bread_1
  2212                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2213                              <1> 	;jmp	error
  2214 000053BE 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2215                              <1> bread_1:
  2216                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2217                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2218                              <1> 	; eAX = Block number (zero based)
  2219                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2220                              <1> preread: ;; call preread
  2221 000053C0 BF[2A670000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2222 000053C5 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2223                              <1> 	;; jc 	error
  2224                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2225                              <1>         ; eAX = Block/Sector number (r1)
  2226                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2227                              <1> 	; 14/03/2013
  2228 000053CA 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2229                              <1>        		; br 1f / branch if block already in a I/O buffer
  2230 000053CC 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2231                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2232 000053D1 E8DA010000          <1> 	call	poke
  2233                              <1>         	; jsr r0,poke / perform the read
  2234                              <1> 	;;jc	error ;2 0/07/2013
  2235                              <1> ; 1:
  2236                              <1>  		; clr *$ps / ps = 0
  2237                              <1>         	; rts r0
  2238                              <1> 	; 12/02/2022
  2239 000053D6 7305                <1> 	jnc	short bread_2
  2240 000053D8 E937010000          <1> 	jmp	dskrd_err
  2241                              <1> 
  2242                              <1> ;; return from preread
  2243                              <1> bread_2:
  2244 000053DD 66810B0040          <1> 	or	word [ebx], 4000h 
  2245                              <1> 		; bis $40000,(r5) 
  2246                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2247                              <1> bread_3: ; 1:
  2248 000053E2 66F7030024          <1> 	test	word [ebx], 2400h
  2249                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2250 000053E7 7407                <1> 	jz	short bread_4
  2251                              <1> 		; beq 1f / no
  2252                              <1> 		; cmp cdev,$1 / disk or drum?
  2253                              <1> 		; ble 2f / yes
  2254                              <1> 		; tstb uquant / is the time quantum = 0?
  2255                              <1> 		; bne 2f / no, 2f
  2256                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2257                              <1> 		; jsr r0,sleep; 31. 
  2258                              <1> 			; / put process to sleep in channel 31 (tape)
  2259                              <1> 		; mov (sp)+,r5 / restore r5
  2260                              <1> 		; br 1b / go back
  2261                              <1> ; 2: / drum or disk
  2262                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2263 000053E9 E8C2F2FFFF          <1> 	call	idle
  2264                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2265 000053EE EBF2                <1> 	jmp	short bread_3
  2266                              <1>        		; br 1b
  2267                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2268 000053F0 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2269                              <1> 		; bic $40000,(r5) / clear bit 14
  2270                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2271 000053F5 83C308              <1> 	add	ebx, 8
  2272                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2273                              <1> 	; 09/06/2015
  2274 000053F8 66833D[27670000]00  <1> 	cmp	word [u.pcount], 0
  2275 00005400 7705                <1> 	ja	short bread_5
  2276 00005402 E880F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2277                              <1> bread_5:
  2278                              <1> 	; eBX = system (I/O) buffer address
  2279 00005407 E870000000          <1> 	call	dioreg
  2280                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2281                              <1> 	; esi = start address of the transfer (in the buffer)
  2282                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2283                              <1> 	; ecx = transfer count (in bytes)
  2284                              <1> 	;
  2285                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2286                              <1> ;   / of users data
  2287 0000540C F3A4                <1> 	rep	movsb
  2288                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2289                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2290                              <1>        		; bne 1b
  2291 0000540E 59                  <1> 	pop	ecx ; **
  2292 0000540F 833D[EC660000]00    <1> 	cmp	dword [u.count], 0
  2293                              <1> 		; tst u.count / done
  2294 00005416 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2295                              <1>        		; beq 1f / yes, return
  2296                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2297                              <1>        		; br bread / read some more
  2298                              <1> ; 1:
  2299 00005418 58                  <1> 	pop	eax ; ****
  2300                              <1>        		; mov (sp)+,r0
  2301 00005419 C3                  <1>         retn		; 09/06/2015
  2302                              <1> 	;jmp	ret_ 
  2303                              <1> 		;jmp ret / jump to routine that called readi
  2304                              <1> 
  2305                              <1> 	; 08/02/2022
  2306                              <1> brw_oov_err:
  2307 0000541A C705[17670000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2307 00005422 0000                <1>
  2308 00005424 E9DFDDFFFF          <1> 	jmp	error
  2309                              <1> 
  2310                              <1> 	; 12/02/2022
  2311                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2312                              <1> 	; 26/04/2013
  2313                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2314                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2315                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2316                              <1> 
  2317                              <1> 	; 12/02/2022				
  2318                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2319                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2320                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2321                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2322                              <1> 
  2323                              <1> bwrite: 
  2324                              <1> 	; 12/02/2022
  2325                              <1> 	; 04/02/2022
  2326                              <1> 	; 14/07/2015
  2327                              <1> 	; 10/07/2015
  2328                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2329                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2330                              <1> 	;	
  2331                              <1> 	;; / write on block structured device
  2332                              <1> 	;
  2333                              <1> 	; INPUTS ->
  2334                              <1> 	;    [u.fofp] points to the block number
  2335                              <1> 	;    CX = maximum block number allowed on device
  2336                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2337                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2338                              <1> 	;    [u.count]	number of bytes to user desires to write
  2339                              <1> 	; OUTPUTS ->
  2340                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2341                              <1> 	;
  2342                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2343                              <1> 	;
  2344                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2345                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2346                              <1> 	;	is increased by 1. For example: If user/program request 
  2347                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2348                              <1> 	;  	the next block number just as 512 byte writing is done.
  2349                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2350                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2351                              <1> 	;       enough to keep byte position/offset of the disk), this
  2352                              <1> 	;	defect will not be corrected, user/program must request
  2353                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2354                              <1> 	;       for achieving correct result. In future version(s), 
  2355                              <1> 	;	this defect will be corrected by using different 
  2356                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2357                              <1> 
  2358                              <1>        		; jsr r0,tstdeve / test the device for an error
  2359                              <1> 	;push	ecx ; **
  2360                              <1> 	;26/04/2013
  2361                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2362 00005429 2C03                <1> 	sub	al, 3
  2363                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2364 0000542B A2[2A670000]        <1> 	mov	[u.brwdev], al
  2365                              <1> 	; 09/06/2015
  2366                              <1> 	;movzx	ebx, al
  2367                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2368                              <1> 	; 04/02/2022 (BugFix)
  2369 00005430 C0E002              <1> 	shl	al, 2 ; * 4
  2370 00005433 8B88[325E0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2371                              <1> bwrite_0:
  2372 00005439 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2373                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2374                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2375 0000543A 8B1D[D8660000]      <1> 	mov	ebx, [u.fofp]
  2376 00005440 8B03                <1> 	mov	eax, [ebx]       
  2377 00005442 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2378                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2379 00005445 39C8                <1> 	cmp	eax, ecx
  2380                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2381                              <1>        	                     ; / block number allowed
  2382                              <1> 	;jnb	error	     ; 18/04/2013
  2383                              <1> 		; bhis error10 / yes, error
  2384                              <1>      	; 12/02/2022
  2385                              <1> 	;jb	short bwrite_1
  2386                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2387                              <1> 	;jmp	error
  2388 00005447 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2389                              <1> bwrite_1:
  2390                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2391                              <1> 		; inc *u.fofp / no, increment block number
  2392                              <1> 	; 09/06/2015 - 10/07/2015
  2393 00005449 66833D[27670000]00  <1> 	cmp	word [u.pcount], 0
  2394 00005451 7705                <1> 	ja	short bwrite_2
  2395 00005453 E82BF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2396                              <1> bwrite_2:
  2397 00005458 BF[2A670000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2398 0000545D E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2399                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2400                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2401 00005462 E815000000          <1>         call	dioreg
  2402                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2403                              <1> 	; esi =  destination address (in the buffer)
  2404                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2405                              <1> 	; ecx =  transfer count (in bytes)
  2406                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2407 00005467 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2408 00005469 F3A4                <1> 	rep	movsb
  2409                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2410                              <1>        		; dec r3 / area to the I/O buffer
  2411                              <1>        		; bne 1b
  2412 0000546B E80D010000          <1> 	call	dskwr
  2413                              <1> 		; jsr r0,dskwr / write it out on the device
  2414 00005470 59                  <1> 	pop	ecx ; **
  2415 00005471 833D[EC660000]00    <1>         cmp     dword [u.count], 0
  2416                              <1> 		; tst u.count / done
  2417 00005478 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2418                              <1> 		; beq 1f / yes, 1f
  2419                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2420                              <1>        		; br bwrite / go back and write next block
  2421                              <1> ; 1:
  2422 0000547A 58                  <1> 	pop	eax ; ****
  2423                              <1>        		; mov (sp)+,r0
  2424 0000547B C3                  <1> 	retn		; 09/06/2015
  2425                              <1>         ;jmp	ret_ 
  2426                              <1> 		; jmp ret / return to routine that called writei
  2427                              <1> ;error10:
  2428                              <1> ;       jmp     error  ; / see 'error' routine
  2429                              <1> 
  2430                              <1> dioreg:
  2431                              <1> 	; 04/02/2022
  2432                              <1> 	; 14/07/2015
  2433                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2434                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2435                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2436                              <1> 	;	
  2437                              <1> 	; bookkeeping on block transfers of data
  2438                              <1> 	;
  2439                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2440                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2441                              <1> 	; 10/07/2015
  2442                              <1> 	; * returns byte offset from beginning of current sector buffer
  2443                              <1> 	; (beginning of data) in ESI
  2444                              <1> 	;
  2445 0000547C 8B0D[EC660000]      <1> 	mov	ecx, [u.count]
  2446                              <1> 		; mov u.count,r3 / move char count to r3
  2447                              <1>         ; 04/02/2022
  2448 00005482 31D2                <1> 	xor	edx, edx
  2449 00005484 B602                <1> 	mov	dh, 2
  2450                              <1> 	; edx = 512
  2451 00005486 39D1                <1> 	cmp	ecx, edx ; 512
  2452                              <1> 	;cmp 	ecx, 512
  2453                              <1> 		; cmp r3,$512. / more than 512. char?
  2454 00005488 7602                <1> 	jna	short dioreg_0
  2455                              <1> 		; blos 1f / no, branch
  2456 0000548A 89D1                <1> 	mov	ecx, edx ; 512
  2457                              <1> 	;mov	ecx, 512
  2458                              <1> 		; mov $512.,r3 / yes, just take 512.
  2459                              <1> dioreg_0:
  2460                              <1> 	; 09/06/2015
  2461 0000548C 663B0D[27670000]    <1> 	cmp	cx, [u.pcount]
  2462 00005493 7607                <1> 	jna	short dioreg_1
  2463 00005495 668B0D[27670000]    <1> 	mov	cx, [u.pcount]
  2464                              <1> dioreg_1:
  2465                              <1> ; 1:
  2466 0000549C 8B15[E8660000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2467                              <1> 	        ; mov u.base,r2 / put users base in r2
  2468 000054A2 010D[F0660000]      <1> 	add	[u.nread], ecx
  2469                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2470 000054A8 290D[EC660000]      <1> 	sub	[u.count], ecx
  2471                              <1> 		; sub r3,u.count / update count
  2472 000054AE 010D[E8660000]      <1> 	add	[u.base], ecx
  2473                              <1> 		; add r3,u.base / update base
  2474                              <1> 	; 10/07/2015
  2475                              <1> 	; Retro UNIX 386 v1 - modification !
  2476                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2477                              <1> 	; (It will point to next byte position instead of next block no.)
  2478 000054B4 8B35[D8660000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2479 000054BA 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2480 000054BC 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2481 000054BE 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2482 000054C3 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2483 000054C5 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2484                              <1> 	; 09/06/2015 - 10/07/2015
  2485 000054C7 66290D[27670000]    <1> 	sub	[u.pcount], cx
  2486 000054CE 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2487 000054D4 8B3D[23670000]      <1> 	mov	edi, [u.pbase]
  2488 000054DA 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2489 000054E0 01D7                <1> 	add	edi, edx
  2490 000054E2 893D[23670000]      <1> 	mov	[u.pbase], edi
  2491 000054E8 010D[23670000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2492 000054EE C3                  <1> 	retn
  2493                              <1> 		; rts r0 / return
  2494                              <1> 
  2495                              <1> dskrd:
  2496                              <1> 	; 12/02/2022
  2497                              <1> 	; 18/08/2015
  2498                              <1> 	; 02/07/2015
  2499                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2500                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2501                              <1> 	;
  2502                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2503                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2504                              <1> 	; (number specified in r1) in the acquired buffer.
  2505                              <1> 	; If the device is busy at the time dskrd is called,	
  2506                              <1> 	; dskrd calls idle.
  2507                              <1> 	; 
  2508                              <1> 	; INPUTS ->
  2509                              <1> 	;    r1 - block number
  2510                              <1> 	;    cdev - current device number 
  2511                              <1> 	; OUTPUTS ->
  2512                              <1> 	;    r5 - points to first data word in I/O buffer
  2513                              <1> 	;
  2514                              <1> 	; ((AX = R1)) input/output
  2515                              <1> 	; ((BX = R5)) output 
  2516                              <1> 	;
  2517                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2518                              <1> 	;
  2519 000054EF E851010000          <1> 	call 	bufaloc
  2520                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2521                              <1> 			       ; / get a free I/O buffer
  2522                              <1> 	;;jc	error ; 20/07/2013
  2523 000054F4 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2524                              <1>        		; br 1f / branch if block already in a I/O buffer
  2525                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2526 000054F6 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2527                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2528                              <1> 		               ; / I/O queue entry for buffer
  2529 000054FB E8B0000000          <1> 	call	poke
  2530                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2531                              <1> 			    ; /	bit 10=1 says read
  2532                              <1> 	; 09/06/2015
  2533                              <1> 	;jnc	short dskrd_1
  2534                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2535                              <1> 	;jmp	error
  2536                              <1> 	; 08/02/2022
  2537 00005500 7212                <1> 	jc	short dskrd_3
  2538                              <1> dskrd_1: ; 1:
  2539                              <1>        		;clr *$ps
  2540 00005502 66F7030024          <1>        	test	word [ebx], 2400h
  2541                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2542                              <1> 				; / jump to idle
  2543 00005507 7407                <1>        	jz	short dskrd_2
  2544                              <1> 		; beq 1f
  2545                              <1>         ;;mov   ecx, [s.wait_]
  2546 00005509 E8A2F1FFFF          <1>        	call	idle
  2547                              <1> 		; jsr r0,idle; s.wait+2
  2548 0000550E EBF2                <1> 	jmp 	short dskrd_1
  2549                              <1>        		; br 1b
  2550                              <1> dskrd_2: ; 1:
  2551 00005510 83C308              <1>         add	ebx, 8
  2552                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2553                              <1> 			  ; / just read in
  2554 00005513 C3                  <1>        	retn
  2555                              <1> 		; rts r0
  2556                              <1> dskrd_err: 
  2557                              <1> 	; 08/02/2022
  2558                              <1> 	; (jump from 'bread' error)
  2559                              <1> dskrd_3:	
  2560                              <1> 	; 08/02/2022
  2561 00005514 803D[2A670000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2562 0000551B 7509                <1> 	jne	short dskrd_4 ; no
  2563                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2564 0000551D C605[2A670000]00    <1> 	mov	byte [u.brwdev], 0
  2565 00005524 EB0A                <1> 	jmp	short dskrd_5
  2566                              <1> dskrd_4:
  2567 00005526 C705[17670000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2567 0000552E 0000                <1>
  2568                              <1> dskrd_5:
  2569 00005530 E9D3DCFFFF          <1> 	jmp	error
  2570                              <1> 
  2571                              <1> bwslot:
  2572                              <1> 	; 04/02/2022
  2573                              <1> 	; 10/07/2015
  2574                              <1> 	;	If the block/sector is not placed in a buffer
  2575                              <1> 	;	before 'wslot', it must be read before
  2576                              <1> 	;	it is written! (Otherwise transfer counts less
  2577                              <1> 	;	than 512 bytes will be able to destroy existing 
  2578                              <1> 	;	data on disk.)
  2579                              <1> 	;
  2580                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2581                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2582                              <1> 	; Retro UNIX 8086 v1 modification !
  2583                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2584                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2585                              <1> 	;	-> eAX = block number
  2586                              <1> 	;
  2587 00005535 E818010000          <1> 	call	bufaloc_0
  2588 0000553A 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2589                              <1> 	; 04/02/2022
  2590                              <1> 	; ebx = buffer header address
  2591                              <1> bwslot_0:
  2592                              <1> 	; 10/07/2015
  2593 0000553C 8B35[D8660000]      <1> 	mov	esi, [u.fofp]
  2594 00005542 8B06                <1> 	mov	eax, [esi]
  2595 00005544 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2596 00005549 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2597                              <1> 		       ; recent disk data must be placed in the buffer
  2598 0000554B 813D[EC660000]0002- <1> 	cmp	dword [u.count], 512
  2598 00005553 0000                <1>
  2599 00005555 730F                <1> 	jnb	short wslot_0	
  2600                              <1> bwslot_1:
  2601 00005557 E89AFFFFFF          <1> 	call	dskrd_0
  2602                              <1> 	; 04/02/2022
  2603                              <1> 	; ebx = buffer data address = buffer header address + 8
  2604 0000555C 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2605 0000555F EB05                <1> 	jmp 	short wslot_0
  2606                              <1> 
  2607                              <1> wslot:
  2608                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2609                              <1> 	; 		(32 bit modifications)
  2610                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2611                              <1> 	;
  2612                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2613                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2614                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2615                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2616                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2617                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2618                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2619                              <1> 	;
  2620                              <1> 	; INPUTS ->
  2621                              <1>  	;    r1 - block number
  2622                              <1> 	;    cdev - current (block/disk) device number
  2623                              <1>  	;
  2624                              <1> 	; OUTPUTS ->
  2625                              <1> 	;    bufp - bits 9 and 15 are set, 
  2626                              <1> 	;           the remainder of the word left unchanged
  2627                              <1> 	;    r5 - points to first data word in I/O buffer
  2628                              <1> 	;
  2629                              <1> 	; ((AX = R1)) input/output
  2630                              <1> 	; ((BX = R5)) output 
  2631                              <1> 	;
  2632                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2633                              <1> 
  2634 00005561 E8DF000000          <1> 	call	bufaloc
  2635                              <1> 	; 10/07/2015
  2636                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2637                              <1>         	; br 1f / word in buffer in r5
  2638                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2639                              <1>         ; eAX = Block/Sector number (r1)
  2640                              <1> wslot_0: ;1:
  2641 00005566 66F7030024          <1>      	test	word [ebx], 2400h
  2642                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2643                              <1> 				; / of I/O queue entry
  2644 0000556B 7407                <1> 	jz	short wslot_1
  2645                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2646                              <1> 		        ; / or not waiting to read)
  2647                              <1> 
  2648                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2649 0000556D E83EF1FFFF          <1> 	call	idle
  2650                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2651                              <1>        	                     ; / idle
  2652 00005572 EBF2                <1> 	jmp	short wslot_0
  2653                              <1> 		; br 1b / till finished
  2654                              <1> wslot_1: ;1:
  2655 00005574 66810B0082          <1> 	or      word [ebx], 8200h
  2656                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2657                              <1>                             	 ; / (write, inhibit bits)
  2658                              <1>        		; clr *$ps / clear processor status
  2659 00005579 83C308              <1> 	add	ebx, 8 ; 11/06/2015
  2660                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2661                              <1> 			  ; / for this block
  2662                              <1> dskwr_1:	; 08/02/2022
  2663 0000557C C3                  <1> 	retn
  2664                              <1> 		; rts r0
  2665                              <1> dskwr:
  2666                              <1> 	; 12/02/2022
  2667                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2668                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2669                              <1> 	;
  2670                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2671                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2672                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2673                              <1> 	; previously has supplied all the information required in the
  2674                              <1> 	; I/O queue entry.
  2675                              <1> 	;
  2676                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2677                              <1> 	;
  2678                              <1> 	;
  2679 0000557D 8B1D[88660000]      <1> 	mov	ebx, [bufp]
  2680 00005583 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2681                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2682                              <1>                                   ; / bottom of queue
  2683 00005588 E823000000          <1> 	call	poke
  2684                              <1> 	; 09/06/2015
  2685 0000558D 73ED                <1> 	jnc	short dskwr_1
  2686                              <1> 	; 12/02/2022
  2687 0000558F 803D[2A670000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2688 00005596 7509                <1> 	jne	short dskwr_0 ; no
  2689                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2690 00005598 C605[2A670000]00    <1> 	mov	byte [u.brwdev], 0
  2691 0000559F EB0A                <1> 	jmp	short dskwr_2
  2692                              <1> dskwr_0:
  2693 000055A1 C705[17670000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2693 000055A9 0000                <1>
  2694                              <1> dskwr_2:
  2695 000055AB E958DCFFFF          <1> 	jmp	error
  2696                              <1> ;dskwr_1:
  2697                              <1> ;	retn
  2698                              <1> 
  2699                              <1> ;ppoke:
  2700                              <1>        		; mov $340,*$ps
  2701                              <1>        		; jsr r0,poke
  2702                              <1>        		; clr *$ps
  2703                              <1> 		; rts r0
  2704                              <1> poke:
  2705                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2706                              <1> 	; 24/10/2015
  2707                              <1> 	; 20/08/2015
  2708                              <1> 	; 18/08/2015
  2709                              <1> 	; 02/07/2015
  2710                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2711                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2712                              <1> 	;
  2713                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2714                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2715                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2716                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2717                              <1> 	;
  2718                              <1> 	; Basic I/O functions for all block structured devices
  2719                              <1> 	;
  2720                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2721                              <1> 	;
  2722                              <1> 	; 20/07/2013 modifications
  2723                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2724                              <1> 	; INPUTS -> 
  2725                              <1> 	;        (EBX = buffer header address)
  2726                              <1> 	; OUTPUTS ->
  2727                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2728                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2729                              <1> 	;		(drive not ready or r/w error!)
  2730                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2731                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2732                              <1> 	;        (also it indicates invalid buffer data)
  2733                              <1> 	;
  2734 000055B0 53                  <1> 	push	ebx
  2735                              <1>        		; mov r1,-(sp)
  2736                              <1>        		; mov r2,-(sp)
  2737                              <1>        		; mov r3,-(sp)
  2738 000055B1 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2739                              <1> 	;
  2740                              <1> 	; 09/06/2015
  2741                              <1> 	; (permit read/write after a disk R/W error)
  2742 000055B2 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2743 000055B4 B001                <1> 	mov	al, 1
  2744 000055B6 D2E0                <1> 	shl	al, cl
  2745 000055B8 8405[B0660000]      <1> 	test 	al, [active] ; busy ? (error)
  2746 000055BE 7408                <1> 	jz	short poke_0
  2747 000055C0 F6D0                <1> 	not	al
  2748 000055C2 2005[B0660000]      <1> 	and	[active], al ; reset busy bit for this device only
  2749                              <1> poke_0:
  2750 000055C8 BE[A8660000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2751                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2752                              <1> 					 ; / I/O queue pointer
  2753                              <1> poke_1: ; 1:
  2754 000055CD 83EE04              <1>         sub	esi, 4
  2755 000055D0 8B1E                <1> 	mov	ebx, [esi]
  2756                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2757 000055D2 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2758 000055D5 F6C406              <1>        	test	ah, 06h
  2759                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2760                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2761                              <1> 			       ; / queue entry
  2762 000055D8 745C                <1>         jz      short poke_5
  2763                              <1> 		; beq 2f / branch to 2f if both are clear
  2764                              <1> 	; 31/07/2013
  2765                              <1> 	;test	ah, 0B0h ; (*)
  2766                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2767                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2768                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2769                              <1> 		; bne 2f / branch if any are set
  2770                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2771                              <1>     		; movb (r1),r3 / get device id
  2772 000055DA 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2773                              <1> 	;mov	edi, ecx ; 26/04/2013
  2774 000055DD 31C0                <1> 	xor 	eax, eax ; 0
  2775                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2776                              <1> 		; tstb deverr(r3) / test for errors on this device
  2777                              <1>        	;jna	short poke_2 
  2778                              <1> 		; beq 3f / branch if no errors
  2779                              <1> 	; 02/07/2015
  2780                              <1> 	;dec	eax
  2781                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2782                              <1>        		; mov $-1,2(r1) / destroy associativity
  2783                              <1> 	;shr	eax, 24
  2784                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2785                              <1> 		; clrb 1(r1) / do not do I/O
  2786                              <1> 	;jmp     short poke_5
  2787                              <1>         ;       ; br 2f
  2788                              <1>                 ; rts r0
  2789                              <1> poke_2: ; 3:
  2790                              <1> 	; 02/07/2015
  2791 000055DF FEC1                <1> 	inc	cl ; 0FFh -> 0
  2792 000055E1 7453                <1> 	jz	short poke_5
  2793 000055E3 FEC0                <1> 	inc	al ; mov ax, 1
  2794 000055E5 FEC9                <1> 	dec	cl
  2795 000055E7 7402                <1> 	jz	short poke_3
  2796                              <1> 	; 26/04/2013 Modification
  2797                              <1> 	;inc	al ; mov ax, 1
  2798                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2799                              <1> 	;jz	short poke_3 ; cl = 0
  2800 000055E9 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2801                              <1> poke_3:
  2802                              <1> 	;test	[active], ax
  2803 000055EB 8405[B0660000]      <1> 	test	[active], al
  2804                              <1> 		; bit $2,active / test disk busy bit
  2805 000055F1 7543                <1> 	jnz     short poke_5
  2806                              <1> 		; bne 2f / branch if bit is set
  2807                              <1> 	;or	[active], ax
  2808 000055F3 0805[B0660000]      <1> 	or	[active], al
  2809                              <1> 		; bis $2,active / set disk busy bit
  2810                              <1> 	;push	ax
  2811                              <1> 	; 04/02/2022
  2812 000055F9 50                  <1> 	push	eax
  2813 000055FA E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2814                              <1> 	;mov    [edi+drv.error], ah
  2815                              <1> 	; 04/02/2022
  2816 000055FF 58                  <1> 	pop	eax
  2817                              <1> 	;pop	ax
  2818 00005600 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2819                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2820                              <1> 	;jna	short poke_4
  2821                              <1> 		; tstb deverr(r3) / test for errors on this device
  2822                              <1>        		; beq 3f / branch if no errors
  2823                              <1> 	; 02/07/2015 (32 bit modification)
  2824                              <1> 	; 20/07/2013
  2825 00005602 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2826                              <1>        		; mov $-1,2(r1) / destroy associativity
  2827 00005609 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2828                              <1> 		; clrb 1(r1) / do not do I/O
  2829 0000560E EB26                <1> 	jmp     short poke_5
  2830                              <1> poke_4:	; 20/07/2013
  2831                              <1> 	; 17/07/2013
  2832 00005610 F6D0                <1> 	not 	al 
  2833 00005612 2005[B0660000]      <1> 	and	[active], al ; reset, not busy
  2834                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2835                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2836 00005618 668B03              <1> 	mov	ax, [ebx]
  2837                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2838 0000561B 66250006            <1>         and	ax, 600h
  2839                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2840 0000561F 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2841                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2842 00005624 C0E403              <1> 	shl	ah, 3
  2843                              <1>        		; rol r3
  2844                              <1>                 ; rol r3
  2845                              <1>                 ; rol r3	
  2846 00005627 660903              <1> 	or	[ebx], ax
  2847                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2848                              <1> 			   ; bits 12 and 13
  2849 0000562A E881F0FFFF          <1> 	call	idle ; 18/01/2014
  2850                              <1> 	;; sti
  2851                              <1> 	;hlt 	; wait for a hardware interrupt
  2852                              <1> 	;; cli
  2853                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2854                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2855                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2856                              <1> 	; method, this procedure will wait for a time according to
  2857                              <1> 	; multi tasking and time sharing concept.
  2858                              <1> 	;
  2859                              <1> 	; 24/10/2015
  2860                              <1> 	;not	ax 
  2861 0000562F 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2862 00005633 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2863                              <1> poke_5: ;2:
  2864 00005636 81FE[88660000]      <1>         cmp     esi, bufp
  2865                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2866                              <1>                             ; / has been scanned
  2867 0000563C 778F                <1> 	ja      short poke_1
  2868                              <1>                ; bhi 1b
  2869                              <1> 	; 24/03/2013
  2870                              <1>        		; mov (sp)+,r3
  2871                              <1>        		; mov (sp)+,r2
  2872                              <1>        		; mov (sp)+,r1
  2873 0000563E 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2874 0000563F 5B                  <1> 	pop 	ebx
  2875                              <1> 	; 02/07/2015 (32 bit modification)
  2876                              <1> 	; 20/07/2013
  2877                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2878 00005640 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2879                              <1> 	;	
  2880                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2881                              <1> 	; or written succesfully; even if an error occurs while
  2882                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2883                              <1> 	;
  2884                              <1> 	; 09/06/2015
  2885 00005643 F5                  <1> 	cmc
  2886 00005644 C3                  <1> 	retn
  2887                              <1>                 ; rts r0
  2888                              <1> 
  2889                              <1> bufaloc:
  2890                              <1> 	; 04/02/2022
  2891                              <1> 	; 20/08/2015
  2892                              <1> 	; 19/08/2015
  2893                              <1> 	; 02/07/2015
  2894                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2895                              <1> 	;	     (32 bit modifications)	
  2896                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2897                              <1> 	;
  2898                              <1> 	; bufaloc - Block device I/O buffer allocation
  2899                              <1> 	; 
  2900                              <1> 	; INPUTS ->
  2901                              <1> 	;    r1 - block number
  2902                              <1> 	;    cdev - current (block/disk) device number
  2903                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2904                              <1> 	; OUTPUTS ->
  2905                              <1> 	;    r5 - pointer to buffer allocated
  2906                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2907                              <1> 	;
  2908                              <1> 	; ((AX = R1)) input/output
  2909                              <1> 	; ((BX = R5)) output
  2910                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2911                              <1> 	;    zf=1 -> block already in a I/O buffer
  2912                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2913                              <1> 	;    ((DL = Device ID))
  2914                              <1> 	;    (((DH = 0 or 1)))
  2915                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2916                              <1> 	;    ((CX and DH will not be used after return)))
  2917                              <1> 
  2918                              <1> 	;;push 	esi ; ***
  2919                              <1> 		; mov r2,-(sp) / save r2 on stack
  2920                              <1>        		; mov $340,*$ps / set processor priority to 7
  2921                              <1> 		; 20/07/2013
  2922                              <1> 	; 26/04/2013
  2923                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2924                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  2925                              <1> 	;add	edi, ebx
  2926                              <1> 	; 09/01/2022
  2927 00005645 0FB63D[AC660000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2928 0000564C 81C7[AE660000]      <1> 	add	edi, rdev
  2929                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2930                              <1> 			;; eDI points to device id.
  2931 00005652 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2932                              <1> 	; 11/06/2015
  2933 00005655 80BB[4E5E0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2934 0000565C 720F                <1> 	jb	short bufaloc_9
  2935 0000565E C705[17670000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2935 00005666 0000                <1>
  2936 00005668 E99BDBFFFF          <1> 	jmp	error
  2937                              <1> bufaloc_9:
  2938 0000566D 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2939                              <1> bufaloc_10: ; 02/07/2015
  2940 0000566F 31ED                <1> 	xor 	ebp, ebp ; 0
  2941 00005671 55                  <1> 	push	ebp ; 0
  2942 00005672 89E5                <1>         mov     ebp, esp	
  2943                              <1> 	;
  2944                              <1> bufaloc_1: ;1:
  2945                              <1> 		; clr -(sp) / vacant buffer
  2946 00005674 BE[88660000]        <1>         mov 	esi, bufp
  2947                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2948                              <1> 			     ; / entrys in buffer area
  2949                              <1> bufaloc_2: ;2:
  2950 00005679 8B1E                <1> 	mov	ebx, [esi]
  2951                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2952                              <1> 			    ; queue entry into r5
  2953 0000567B 66F70300F6          <1> 	test	word [ebx], 0F600h
  2954                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2955 00005680 7503                <1>         jnz	short bufaloc_3
  2956                              <1> 		; bne 3f / branch when 
  2957                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2958                              <1>                        ; / (i.e., buffer busy)
  2959 00005682 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2960                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2961                              <1> 			; / found points to word 2 of I/O queue entry)
  2962                              <1> bufaloc_3: ;3:
  2963                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2964                              <1> 	;
  2965 00005685 3813                <1> 	cmp	[ebx], dl	
  2966                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2967                              <1> 			       ; / as current device
  2968 00005687 7508                <1> 	jne	short bufaloc_4
  2969                              <1>        		; bne 3f
  2970 00005689 394304              <1> 	cmp	[ebx+4], eax
  2971                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2972                              <1> 			     ; / same as current block number
  2973 0000568C 7503                <1>        	jne	short bufaloc_4
  2974                              <1> 		; bne 3f
  2975                              <1> 	;add	esp, 4
  2976 0000568E 59                  <1> 	pop	ecx
  2977                              <1>        		; tst (sp)+ / bump stack pointer
  2978 0000568F EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2979                              <1> 				; jump to bufaloc_6 in original Unix v1
  2980                              <1>        		; br 1f / use this buffer
  2981                              <1> bufaloc_4: ;3:
  2982 00005691 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2983                              <1> 	;
  2984 00005694 81FE[A0660000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2985                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2986 0000569A 72DD                <1> 	jb	short bufaloc_2
  2987                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2988                              <1>                        ; / buffers not checked)
  2989 0000569C 5E                  <1>         pop	esi
  2990                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2991                              <1> 			     ; / to last free block
  2992 0000569D 09F6                <1>        	or	esi, esi 
  2993 0000569F 7507                <1> 	jnz	short bufaloc_5
  2994                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2995                              <1> 	        ; / if a free buffer is found branch to 2f
  2996                              <1>         ;; mov  ecx, [s.wait_]
  2997 000056A1 E80AF0FFFF          <1> 	call	idle
  2998                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2999 000056A6 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3000                              <1>        		; br 1b
  3001                              <1> bufaloc_5: ;2:
  3002                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3003 000056A8 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3004                              <1> bufaloc_6: ;1:
  3005 000056AA 8B1E                <1>         mov    	ebx, [esi] 
  3006                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3007                              <1> 			     ; / entry in r5
  3008                              <1> 	;; 26/04/2013
  3009                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3010 000056AC 8813                <1> 	mov 	[ebx], dl
  3011                              <1> 		; movb cdev,(r5) / put current device number 
  3012                              <1> 				 ; / in I/O queue entry
  3013 000056AE 894304              <1> 	mov 	[ebx+4], eax
  3014                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3015                              <1> 			     ; / of I/O queue entry
  3016                              <1> bufaloc_7: ;1:
  3017 000056B1 81FE[88660000]      <1>         cmp	esi, bufp
  3018                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3019                              <1> 			     ; / and put latest assigned
  3020 000056B7 760A                <1> 	jna	short bufaloc_8	
  3021                              <1>        		; blos 1f / buffer on the top 
  3022                              <1> 			; / (this makes if the lowest priority)
  3023 000056B9 83EE04              <1> 	sub	esi, 4
  3024 000056BC 8B0E                <1> 	mov	ecx, [esi]
  3025 000056BE 894E04              <1> 	mov	[esi+4], ecx
  3026                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3027 000056C1 EBEE                <1> 	jmp 	short bufaloc_7        
  3028                              <1> 		; br 1b
  3029                              <1> bufaloc_8: ;1:
  3030 000056C3 891E                <1>         mov	[esi], ebx
  3031                              <1> 		; mov r5,(r2)
  3032                              <1> 	;;pop	esi ; ***
  3033                              <1>        		; mov (sp)+,r2 / restore r2
  3034 000056C5 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3035                              <1> 		; Retro UNIX 8086 v1 modification
  3036                              <1> 		; zf=1 --> block already is in an I/O buffer
  3037                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3038 000056C7 C3                  <1> 	retn
  3039                              <1> 		; rts r0
  3040                              <1> 
  3041                              <1> 
  3042                              <1> diskio:
  3043                              <1> 	; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21)
  3044                              <1> 	; ((Ref: Retro UNIX 386 v1.1 'diskio' modification: 12/07/2022))
  3045                              <1> 	; 
  3046                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3047                              <1> 	;	((simplified and shortened 'diskio.s' code)
  3048                              <1> 	;
  3049                              <1> 	; 12/02/2022
  3050                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  3051                              <1> 	; 10/07/2015
  3052                              <1> 	; 02/07/2015
  3053                              <1> 	; 16/06/2015
  3054                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3055                              <1> 	;	     (80386 protected mode modifications)	
  3056                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3057                              <1> 	;
  3058                              <1> 	; Retro UNIX 8086 v1 feature only !
  3059                              <1> 	;
  3060                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3061                              <1> 	; 04/07/2009 - 20/07/2011
  3062                              <1> 	;
  3063                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3064                              <1> 	;
  3065                              <1>         ; INPUTS ->
  3066                              <1> 	; 	   eBX = System I/O Buffer header address
  3067                              <1> 	;
  3068                              <1>         ; OUTPUTS -> cf=0 --> done 
  3069                              <1> 	; 	     cf=1 --> error code in AH
  3070                              <1> 	;
  3071                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3072                              <1> 	
  3073                              <1> ;rw_disk_sector:
  3074                              <1> 	; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21)
  3075                              <1> 	; 12/02/2022
  3076                              <1> 	; 10/07/2015
  3077                              <1> 	; 02/07/2015
  3078                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3079                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3080                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3081                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3082                              <1> 	;
  3083                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3084                              <1> 	;mov	dh, 2
  3085                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3086 000056C8 B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3087 000056CA 668B03              <1> 	mov	ax, [ebx]
  3088                              <1> 	;
  3089 000056CD 56                  <1> 	push	esi ; ****
  3090 000056CE 53                  <1> 	push	ebx ; ***
  3091                              <1> 	;
  3092 000056CF 0FB6C8              <1> 	movzx	ecx, al
  3093 000056D2 89CE                <1> 	mov	esi, ecx
  3094                              <1> 	;
  3095 000056D4 38F1                <1> 	cmp	cl, dh ; 2
  3096 000056D6 7202                <1> 	jb	short rwdsk0
  3097 000056D8 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3098                              <1> rwdsk0:
  3099                              <1> 	; 12/07/2022
  3100                              <1> 	;mov	[drv], al
  3101 000056DA 81C6[4E5E0000]      <1> 	add	esi, drv.status
  3102                              <1> 	; 11/06/2015
  3103 000056E0 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3104 000056E3 7204                <1> 	jb      short rwdsk1
  3105                              <1> 	; 'drive not ready' error
  3106                              <1> 	; 12/02/2022
  3107                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3108                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3109                              <1> 	;;jmp	error
  3110                              <1> 	;stc	; cf = 1
  3111                              <1> 	;retn
  3112                              <1> 	; 12/02/2022
  3113 000056E5 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3114 000056E7 EB1F                <1> 	jmp	short rwdsk_err1
  3115                              <1> rwdsk1:
  3116                              <1> 	;test	ah, 2
  3117                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3118                              <1> 	;		 ; write bit
  3119                              <1> 	;jz	short rwdsk2
  3120                              <1> 	
  3121                              <1> 	;;test	ah, 4
  3122                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3123                              <1> 	;;		 ; read bit
  3124                              <1> 	;;jz	short diskio_ret
  3125                              <1> 
  3126                              <1> 	;inc	dh ; 03h = write
  3127                              <1> 
  3128                              <1> 	; 08/07/2022
  3129 000056E9 84F4                <1> 	test	ah, dh ; test ah, 2
  3130 000056EB 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3131 000056ED FECE                <1> 	dec	dh
  3132                              <1> 		; dh = 01h = read
  3133                              <1> rwdsk2:
  3134 000056EF 88C2                <1> 	mov	dl, al
  3135 000056F1 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3136 000056F4 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3137 000056F6 C0E102              <1> 	shl	cl, 2
  3138 000056F9 81C1[325E0000]      <1> 	add	ecx, drv.size ; disk size
  3139 000056FF 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3140 00005701 7214                <1> 	jb      short rwdsk3
  3141                              <1>  	; 'out of volume' error
  3142                              <1> 	; 12/02/2022
  3143                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3144                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3145                              <1> 	;;jmp	error
  3146                              <1> 	;stc	; cf = 1
  3147                              <1> 	;retn
  3148                              <1> 	; 12/02/2022
  3149 00005703 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3150                              <1> rwdsk_err1:
  3151 00005708 C605[2A670000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3152 0000570F 890D[17670000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3153 00005715 EB27                <1> 	jmp	short rwdsk_err2
  3154                              <1> rwdsk3:
  3155                              <1> 	; 11/06/2015
  3156 00005717 83C304              <1> 	add	ebx, 4 ; buffer address
  3157 0000571A C605[46670000]04    <1> 	mov	byte [retry_count], 4
  3158                              <1> 	; 12/07/2022
  3159                              <1> 	;test	byte [esi], 1 ; LBA ready ?
  3160                              <1>         ;jz	short rwdsk_chs
  3161                              <1> rwdsk_lba:
  3162                              <1> 	; LBA read/write (with private LBA function) 
  3163                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3164 00005721 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3165 00005724 89C1                <1> 	mov	ecx, eax ; sector number
  3166                              <1> 	; ebx = buffer (data) address
  3167                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3168                              <1> rwdsk_lba_retry:
  3169                              <1> 	;mov	dl, [drv]
  3170                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3171                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3172                              <1> 	;;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3173                              <1> 	;mov	ah, 2 ; LBA write function number - 2
  3174                              <1> 	;add	ah, dh		
  3175                              <1> 	;mov	al, 1
  3176                              <1> 	;int	13h
  3177                              <1> 	;call	int13h
  3178                              <1> 	; 12/07/2022
  3179 00005726 88F0                <1> 	mov	al, dh	; function (1 or 2)
  3180                              <1> 			; (1 = read, 2 = write )
  3181                              <1> 	; ecx = disk sector address (LBA)
  3182                              <1> 	; ebx = buffer address
  3183                              <1> 	;  dl = (physical) disk number
  3184                              <1> 	;  al = function (r/w)
  3185 00005728 E867C9FFFF          <1> 	call	DISK_IO
  3186                              <1> 
  3187 0000572D 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3188 0000572F 730E                <1> 	jnc	short rwdsk_lba_ok
  3189 00005731 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3190 00005734 7408                <1>         je      short rwdsk_lba_fails
  3191 00005736 FE0D[46670000]      <1> 	dec	byte [retry_count]
  3192 0000573C 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3193                              <1> rwdsk_err2:	; 12/02/2022
  3194                              <1> rwdsk_lba_fails:
  3195 0000573E F9                  <1> 	stc
  3196                              <1> rwdsk_lba_ok:
  3197 0000573F 5B                  <1> 	pop	ebx ; ***
  3198 00005740 5E                  <1> 	pop	esi ; ****
  3199 00005741 C3                  <1> 	retn
  3200                              <1> rwdsk_lba_reset:
  3201                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3202                              <1> 	;int	13h
  3203                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3204                              <1> 	;mov	ah, 5 ; Alternate reset	 
  3205                              <1> 	;call	int13h
  3206                              <1> 	;jnc	short rwdsk_lba_retry
  3207                              <1> 	; 12/07/2022
  3208 00005742 30C0                <1> 	xor	al, al ; 0 ; reset
  3209 00005744 E84BC9FFFF          <1> 	call	DISK_IO
  3210 00005749 73DB                <1> 	jnc	short rwdsk_lba_retry
  3211                              <1> 
  3212 0000574B 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3213 0000574D EBF0                <1> 	jmp	short rwdsk_lba_ok
  3214                              <1> 
  3215                              <1> 	; 12/07/2022 
  3216                              <1> 	;	(CHS Read/Write setup is not needed here.)
  3217                              <1> 	; 	(LBA address will be converted to CHS parameters
  3218                              <1> 	;	in 'DISK_IO' procedure when/if it is required.)
  3219                              <1> 	
  3220                              <1> ;	; CHS read (convert LBA address to CHS values)	
  3221                              <1> ;rwdsk_chs:
  3222                              <1> ;	; 10/07/2015
  3223                              <1> ;	sub	esi, drv.status
  3224                              <1> ;	mov	ecx, esi
  3225                              <1> ;	add 	esi, drv.error
  3226                              <1> ;	; 02/07/2015
  3227                              <1> ;	; 16/06/2015
  3228                              <1> ;	; 11/06/2015 
  3229                              <1> ;	push	ebx ; ** ; buffer
  3230                              <1> ;	shl	ecx, 1
  3231                              <1> ;	push	ecx ; * 
  3232                              <1> ;	;
  3233                              <1> ;	mov	ebx, ecx
  3234                              <1> ;	mov	[rwdsk], dh ; 02/07/2015
  3235                              <1> ;	xor	edx, edx ; 0
  3236                              <1> ;	; 04/02/2022
  3237                              <1> ;	;sub	ecx, ecx 
  3238                              <1> ;	add     ebx, drv.spt
  3239                              <1> ;	mov	cx, [ebx] ; sector per track
  3240                              <1> ;		; EDX:EAX = LBA
  3241                              <1> ;	div	ecx
  3242                              <1> ;	mov	cl, dl	; sector number - 1
  3243                              <1> ;	inc	cl	; sector number (1 based)
  3244                              <1> ;	pop	ebx ; * ; 11/06/2015
  3245                              <1> ;	;push	cx
  3246                              <1> ;	; 04/02/2022
  3247                              <1> ;	push	ecx
  3248                              <1> ;	add     ebx, drv.heads
  3249                              <1> ;	mov	cx, [ebx] ; heads
  3250                              <1> ;	xor	edx, edx
  3251                              <1> ;		; EAX = cylinders * heads + head
  3252                              <1> ;	div	ecx
  3253                              <1> ;	;pop	cx     ; sector number
  3254                              <1> ;	; 04/02/2022
  3255                              <1> ;	pop	ecx
  3256                              <1> ;	mov	dh, dl ; head number
  3257                              <1> ;	mov	dl, [drv]
  3258                              <1> ;	mov	ch, al ; cylinder (bits 0-7)
  3259                              <1> ;	shl	ah, 6
  3260                              <1> ;	or	cl, ah ; cylinder (bits 8-9)
  3261                              <1> ;		       ; sector (bits 0-7)
  3262                              <1> ;	pop	ebx ; ** ; buffer ; 11/06/2015
  3263                              <1> ;		; CL = sector (bits 0-5)
  3264                              <1> ;		;      cylinder (bits 8-9 -> bits 6-7)
  3265                              <1> ;		; CH = cylinder (bits 0-7)
  3266                              <1> ;		; DH = head
  3267                              <1> ;		; DL = drive
  3268                              <1> ;	;
  3269                              <1> ;	mov	byte [retry_count], 4
  3270                              <1> ;rwdsk_retry:	
  3271                              <1> ;	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3272                              <1> ;	; 08/07/2022
  3273                              <1> ;	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3274                              <1> ;	mov	al, 1 ; sector count	
  3275                              <1> ;	;int	13h
  3276                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3277                              <1> ;	call	int13h
  3278                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3279                              <1> ;	jnc	short rwdsk_ok ; ah = 0
  3280                              <1> ;	cmp	ah, 80h ; time out ?
  3281                              <1> ;	je	short rwdsk_fails
  3282                              <1> ;	dec	byte [retry_count]
  3283                              <1> ;	jnz	short rwdsk_reset
  3284                              <1> ;rwdsk_fails:
  3285                              <1> ;	stc
  3286                              <1> ;rwdsk_ok:
  3287                              <1> ;	pop	ebx ; ***
  3288                              <1> ;	pop	esi ; ****
  3289                              <1> ;	retn
  3290                              <1> ;rwdsk_reset:
  3291                              <1> ;	; 02/02/2015
  3292                              <1> ;	sub	ah, ah
  3293                              <1> ;	cmp	dl, 80h
  3294                              <1> ;	jb	short rwdsk_fd_reset
  3295                              <1> ;	;mov	ah, 0Dh ; Alternate reset
  3296                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3297                              <1> ;	mov	ah, 5  ; Alternate reset
  3298                              <1> ;rwdsk_fd_reset:
  3299                              <1> ;	;int	13h
  3300                              <1> ;	call	int13h
  3301                              <1> ;	jnc	short rwdsk_retry
  3302                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3303                              <1> ;	jmp 	short rwdsk_ok
  3304                              <1> 
  3305                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3306                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3307                              <1> ;
  3308                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3309                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3310                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3311                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3312                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3313                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3314                              <1> ; as in original unix v1.
  3315                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3316                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3317                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3318                              <1> ;
  3319                              <1> ; Erdogan tan (10/07/2015) 
  3320                              <1> 
  3321                              <1> ;drum: / interrupt handler
  3322                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3323                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3324                              <1> ;                                      / error
  3325                              <1> ;               br 3f / no, error
  3326                              <1> ;       br      2f / error
  3327                              <1> ;
  3328                              <1> ;disk:
  3329                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3330                              <1> ;       jmp     *$0f
  3331                              <1> ;0:
  3332                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3333                              <1> ;      	        br 3f / no, errors
  3334                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3335                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3336                              <1> ;                        / to 1f
  3337                              <1> ;       br      4f
  3338                              <1> ;1:
  3339                              <1> ;       bit     $20000,rkcs
  3340                              <1> ;       beq     4f / wait for seek complete
  3341                              <1> ;       mov     $0b,0b-2
  3342                              <1> ;       mov     rkap,r1
  3343                              <1> ;2:
  3344                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3345                              <1> ;                          / the disk buffer
  3346                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3347                              <1> ;       inc     r1
  3348                              <1> ;       asr     (r1)
  3349                              <1> ;       asr     (r1)
  3350                              <1> ;       asr     (r1) / reissue request
  3351                              <1> ;       dec     r1
  3352                              <1> ;3:
  3353                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3354                              <1> ;       mov     ac,-(sp)
  3355                              <1> ;       mov     mq,-(sp) / put these on the stack
  3356                              <1> ;       mov     sc,-(sp)
  3357                              <1> ;       jsr     r0,poke
  3358                              <1> ;       mov     (sp)+,sc
  3359                              <1> ;       mov     (sp)+,mq / pop them off stack
  3360                              <1> ;       mov     (sp)+,ac
  3361                              <1> ;4:
  3362                              <1> ;       jmp     retisp / u4-3
  3363                              <1> ;
  3364                              <1> ;trapt:                  / r2 points to the
  3365                              <1> ;       mov     (r0)+,r2 / device control register
  3366                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3367                              <1> ;       tst     (sp)+
  3368                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3369                              <1> ;       bge     4b / device still active so branch
  3370                              <1> ;       bit     (r0),active / was device busy?
  3371                              <1> ;       beq     4b / no, stray interrupt
  3372                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3373                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3374                              <1> ;       bge     2f / if no error jump to 2f
  3375                              <1> ;       tst     (r0)+ / skip on error
  3376                              <1> ; 2:
  3377                              <1> ;       jmp     (r0)
  2057                                  %include 'u9.s'        ; 29/06/2015
  2058                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS9.INC
  2059                              <1> ; Last Modification: 13/06/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 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2070                              <1> ;
  2071                              <1> ; ****************************************************************************
  2072                              <1> ; 21/11/2015
  2073                              <1> 
  2074                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) - Printer BIOS (Functions)
  2075                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2076                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2077                              <1> 
  2078                              <1> getch:
  2079                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2080                              <1> 	; 30/06/2015
  2081                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2082 0000574F 28C0                <1> 	sub	al, al ; 0
  2083                              <1> getch_q: ; 06/08/2015
  2084 00005751 8A25[36630000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2085 00005757 EB06                <1>         jmp     short getc_n
  2086                              <1> 
  2087                              <1> getc: 
  2088                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2089                              <1> 	; 12/11/2015
  2090                              <1> 	; 15/09/2015
  2091                              <1> 	; 01/07/2015
  2092                              <1> 	; 30/06/2015
  2093                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2094                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2095                              <1> 	;
  2096                              <1> 	; Retro UNIX 8086 v1 modification !
  2097                              <1> 	; 
  2098                              <1> 	; 'getc' gets (next) character 
  2099                              <1> 	;	 from requested TTY (keyboard) buffer 
  2100                              <1> 	; INPUTS ->
  2101                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2102                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2103                              <1> 	;	(Keyboard buffer will point to 
  2104                              <1> 	;			next character at next call)
  2105                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2106                              <1> 	;	(Keyboard buffer will point to 
  2107                              <1> 	;			current character at next call)
  2108                              <1> 	; OUTPUTS ->
  2109                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2110                              <1> 	;     			 ZF=0 -> AX has (current) character
  2111                              <1> 	;      AL = ascii code
  2112                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2113                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2114                              <1> 	; Original UNIX V1 'getc': 
  2115                              <1> 	;		get a character off character list
  2116                              <1> 	;
  2117                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2118                              <1> 	;
  2119                              <1> 	; 30/06/2015 (32 bit modifications)
  2120                              <1> 	; 16/07/2013
  2121                              <1> 	; mov 	[getctty], ah
  2122                              <1> 	;
  2123                              <1> 
  2124 00005759 8A25[16670000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2125                              <1> getc_n:
  2126                              <1> 	; 30/06/2015
  2127 0000575F 08E4                <1> 	or	ah, ah
  2128 00005761 740D                <1> 	jz	short getc0 
  2129 00005763 D0E4                <1> 	shl	ah, 1
  2130 00005765 0FB6DC              <1> 	movzx	ebx, ah
  2131 00005768 81C3[38630000]      <1> 	add	ebx, ttychr
  2132 0000576E EB05                <1> 	jmp	short getc1
  2133                              <1> getc0:
  2134 00005770 BB[38630000]        <1> 	mov	ebx, ttychr
  2135                              <1> getc1:
  2136 00005775 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2137                              <1> 				; (by kb_int)	
  2138 00005778 6609C9              <1> 	or	cx, cx
  2139 0000577B 7507                <1> 	jnz	short getc2
  2140 0000577D 20C0                <1> 	and 	al, al
  2141 0000577F 7415                <1> 	jz	short getc_s
  2142                              <1> 	;xor	ax, ax
  2143                              <1> 	; 24/12/2021
  2144 00005781 31C0                <1> 	xor	eax, eax
  2145 00005783 C3                  <1> 	retn
  2146                              <1> getc2:	
  2147 00005784 20C0                <1> 	and	al, al
  2148 00005786 6689C8              <1> 	mov	ax, cx
  2149 00005789 66B90000            <1> 	mov	cx, 0
  2150 0000578D 7506                <1> 	jnz	short getc3
  2151                              <1> getc_sn:
  2152 0000578F 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2153 00005792 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2154                              <1> getc3:
  2155 00005795 C3                  <1> 	retn
  2156                              <1> getc_s:
  2157                              <1> 	; 12/11/2015
  2158                              <1> 	; 15/09/2015
  2159                              <1> 	; 01/07/2015
  2160                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2161                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2162                              <1> 	;
  2163                              <1> 	; tty  of the current process is not 
  2164                              <1> 	; current tty (ptty); so, current process only 
  2165                              <1> 	; can use keyboard input when its tty becomes 
  2166                              <1> 	; current tty (ptty).
  2167                              <1> 	; 'sleep' is for preventing an endless lock
  2168                              <1> 	; during this tty input request.
  2169                              <1> 	; (Because, the user is not looking at the video page
  2170                              <1> 	; of the process to undersand there is a keyboard
  2171                              <1> 	; input request.)
  2172                              <1> 	;
  2173                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2174                              <1> 	;
  2175                              <1> 	; 05/10/2013
  2176                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2177                              <1> 	;
  2178                              <1> 	; 10/10/2013
  2179                              <1> gcw0:
  2180 00005796 B10A                <1> 	mov	cl, 10 ; ch = 0
  2181                              <1> gcw1:	
  2182                              <1> 	; 12/11/2015
  2183 00005798 E86FDBFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2184                              <1> 	; 10/10/2013
  2185 0000579D E80EEFFFFF          <1> 	call	idle
  2186 000057A2 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2187                              <1> 				; (by kb_int)
  2188 000057A5 6609C0              <1> 	or	ax, ax
  2189                              <1> ;	jnz	short gcw3
  2190 000057A8 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2191                              <1> 	; 30/06/2015
  2192 000057AA FEC9                <1> 	dec	cl
  2193 000057AC 75EA                <1> 	jnz	short gcw1
  2194                              <1> 	;
  2195 000057AE 8A25[16670000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2196                              <1> ;	; 10/12/2013
  2197                              <1> ;	cmp 	ah, [ptty]
  2198                              <1> ;	jne	short gcw2
  2199                              <1> ;	; 14/02/2014
  2200                              <1> ;	cmp	byte [u.uno], 1
  2201                              <1> ;	jna	short gcw0		
  2202                              <1> ;gcw2:
  2203 000057B4 E884EFFFFF          <1> 	call	sleep
  2204                              <1> 	;
  2205                              <1> 	; 20/09/2013
  2206 000057B9 8A25[16670000]      <1> 	mov	ah, [u.ttyn]
  2207 000057BF 30C0                <1> 	xor 	al, al
  2208 000057C1 EB9C                <1> 	jmp	short getc_n
  2209                              <1> ;gcw3:
  2210                              <1> gcw2: 	; 15/09/2015
  2211                              <1> 	; 10/10/2013
  2212 000057C3 30C9                <1> 	xor	cl, cl
  2213 000057C5 EBC8                <1> 	jmp	short getc_sn
  2214                              <1> 
  2215                              <1> putc:	
  2216                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2217                              <1> 	; 13/08/2015
  2218                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2219                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2220                              <1> 	;
  2221                              <1> 	; Retro UNIX 8086 v1 modification !
  2222                              <1> 	; 
  2223                              <1> 	; 'putc' puts a character 
  2224                              <1> 	;	 onto requested (tty) video page or
  2225                              <1> 	;	 serial port
  2226                              <1> 	; INPUTS ->
  2227                              <1> 	;     AL = ascii code of the character
  2228                              <1> 	;     AH = video page (tty) number (0 to 7)
  2229                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2230                              <1> 	; OUTPUTS ->
  2231                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2232                              <1> 	;      			ZF=0 -> AX has (current) character
  2233                              <1> 	;     cf=0 and AH = 0 -> no error
  2234                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2235                              <1> 	; 
  2236                              <1> 	; Original UNIX V1 'putc': 
  2237                              <1> 	;     put a character at the end of character list
  2238                              <1> 	;
  2239                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2240                              <1> 	;
  2241 000057C7 80FC07              <1> 	cmp	ah, 7
  2242                              <1>         ;ja	sndc
  2243 000057CA 770A                <1>         ja      short sndc ; 24/12/2024
  2244                              <1> 	; 30/06/2015
  2245 000057CC 0FB6DC              <1> 	movzx	ebx, ah
  2246                              <1> 	; 13/08/2015
  2247 000057CF B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2248 000057D1 E9E6BBFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2249                              <1> 
  2250                              <1> sndc:   ; <Send character>
  2251                              <1> 	;
  2252                              <1> 	; 12/01/2022
  2253                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2254                              <1> 	; 17/11/2015
  2255                              <1> 	; 16/11/2015
  2256                              <1> 	; 11/11/2015
  2257                              <1> 	; 10/11/2015
  2258                              <1> 	; 09/11/2015
  2259                              <1> 	; 08/11/2015
  2260                              <1> 	; 07/11/2015
  2261                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2262                              <1> 	; 29/10/2015
  2263                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2264                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2265                              <1> 	;
  2266                              <1> 	; Retro UNIX 8086 v1 feature only !
  2267                              <1> 	;
  2268                              <1> 	; ah = [u.ttyn]
  2269                              <1> 	;
  2270                              <1> 	; 30/06/2015
  2271 000057D6 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2272                              <1> 	; 07/11/2015
  2273 000057D9 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2274                              <1> sndc0:
  2275                              <1> 	; 07/11/2015
  2276 000057DC E8AAEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2277 000057E1 7405                <1> 	jz	short sndc1
  2278 000057E3 E824DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2279                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2280                              <1> sndc1:
  2281                              <1> 	; 16/11/2015
  2282                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2283                              <1> 	; 24/12/2021
  2284 000057E8 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2285                              <1> sndcx:
  2286 000057EA 8A83[7A630000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2287 000057F0 8AA3[78630000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2288                              <1> 	;
  2289                              <1> 	; 17/11/2015
  2290                              <1> 	; check 'request for response' status
  2291 000057F6 80BB[74630000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2292 000057FD 740A                <1> 	jz	short query
  2293                              <1> response:
  2294 000057FF FE05[77630000]      <1> 	inc 	byte [comqr] ; query or response status
  2295 00005805 B0FF                <1> 	mov	al, 0FFh	 
  2296 00005807 EB14                <1> 	jmp	short sndc3
  2297                              <1> query:
  2298 00005809 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2299 0000580B 750E                <1> 	jnz 	short sndc2 ; normal character
  2300                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2301                              <1> 	;je	short sndc2  ; yes, already responded
  2302                              <1> 	; 16/11/2015
  2303                              <1> 	; query: request for response (again)
  2304 0000580D 8883[78630000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2305 00005813 FE05[77630000]      <1> 	inc 	byte [comqr] ; query or response status
  2306 00005819 EB02                <1> 	jmp	short sndc3
  2307                              <1> sndc2:
  2308 0000581B 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2309                              <1> sndc3:
  2310 0000581D 8883[7A630000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2311 00005823 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2312                              <1> 	; 30/06/2015
  2313 00005825 E891D4FFFF          <1> 	call	sp_status ; get serial port status
  2314                              <1> 	; AL = Line status, AH = Modem status
  2315                              <1> 	; 07/11/2015
  2316 0000582A A880                <1> 	test	al, 80h
  2317 0000582C 7504                <1> 	jnz	short sndc4
  2318 0000582E A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2319 00005830 751A                <1> 	jnz	short sndc5
  2320                              <1> sndc4: 	; Check line status again
  2321                              <1> 	; 16/11/2015
  2322                              <1> 	;push	cx
  2323                              <1> 	; 24/12/2021
  2324 00005832 51                  <1> 	push	ecx
  2325                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2326                              <1> 	; 12/01/2022
  2327 00005833 31C9                <1> 	xor	ecx, ecx
  2328 00005835 B106                <1> 	mov	cl, 6
  2329 00005837 E877BCFFFF          <1> 	call	WAITF
  2330                              <1> 	;pop	cx
  2331                              <1> 	; 24/12/1021
  2332 0000583C 59                  <1> 	pop	ecx
  2333                              <1> 	;
  2334 0000583D 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2335 0000583F E877D4FFFF          <1> 	call	sp_status ; get serial port status
  2336                              <1> 	; 16/11/2015
  2337                              <1> 	; 09/11/2015
  2338                              <1> 	; 08/11/2015
  2339 00005844 A880                <1> 	test	al, 80h	; time out error
  2340 00005846 7565                <1>         jnz     short sndc7
  2341 00005848 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2342 0000584A 7461                <1>         jz	short sndc7
  2343                              <1> sndc5:  
  2344 0000584C 8A83[7A630000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2345 00005852 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2346 00005856 28DE                <1> 	sub	dh, bl
  2347 00005858 EE                  <1> 	out	dx, al	   ; send on serial port
  2348                              <1> 	; 10/11/2015
  2349                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2350                              <1> 	; (to improve text flow to the terminal)
  2351                              <1> 	; ('diskette.inc': 'WAITF')
  2352                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2353                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2354                              <1> 	;push	cx
  2355                              <1> 	; 24/12/2021
  2356 00005859 51                  <1> 	push	ecx
  2357                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2358                              <1> 	; 12/01/2022
  2359 0000585A 29C9                <1> 	sub	ecx, ecx
  2360 0000585C B106                <1> 	mov	cl, 6
  2361 0000585E E850BCFFFF          <1> 	call	WAITF
  2362                              <1> 	;pop	cx
  2363                              <1> 	; 24/12/1021
  2364 00005863 59                  <1> 	pop	ecx
  2365                              <1>     	;
  2366                              <1> 	; 07/11/2015
  2367 00005864 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2368                              <1> 	;
  2369 00005866 E850D4FFFF          <1> 	call	sp_status ; get serial port status
  2370                              <1> 	; AL = Line status, AH = Modem status
  2371                              <1> 	;
  2372 0000586B E81BEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2373 00005870 7405                <1> 	jz	short sndc6
  2374 00005872 E895DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2375                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2376                              <1> sndc6:
  2377 00005877 3C80                <1> 	cmp	al, 80h
  2378 00005879 7332                <1> 	jnb	short sndc7		
  2379                              <1> 	;
  2380 0000587B 803D[77630000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2381 00005882 7244                <1> 	jb	short sndc8 	; no, normal character
  2382 00005884 883D[77630000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2383                              <1> 	; 17/11/2015
  2384 0000588A E821EEFFFF          <1> 	call	idle
  2385                              <1> 	;
  2386 0000588F 38BB[7A630000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2387                              <1>         ;ja	sndc2       ; response (will be followed by
  2388                              <1> 			    ; a normal character)
  2389                              <1> 	; 24/12/2021
  2390 00005895 7602                <1> 	jna	short sndc_10
  2391 00005897 EB82                <1> 	jmp	sndc2
  2392                              <1> sndc_10:
  2393                              <1> 	; Query request must be responded by the terminal
  2394                              <1> 	; before sending a normal character !
  2395 00005899 53                  <1> 	push	ebx
  2396                              <1> 	;push	cx ; *** cl = character (to be sent)
  2397                              <1> 	; 24/12/2021
  2398 0000589A 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2399 0000589B 8A25[16670000]      <1> 	mov	ah, [u.ttyn]
  2400 000058A1 E897EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2401                              <1> 		      ; received data available interrupt
  2402                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2403                              <1> 	; 24/12/2021
  2404 000058A6 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2405 000058A7 5B                  <1> 	pop	ebx
  2406 000058A8 E93DFFFFFF          <1>         jmp	sndcx
  2407                              <1> sndc7:
  2408                              <1> 	 ; 16/11/2015
  2409 000058AD 803D[77630000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2410 000058B4 7213                <1> 	jb	short sndc9 	; no
  2411                              <1> 	;
  2412 000058B6 88BB[78630000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2413 000058BC 88BB[7A630000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2414                              <1> 	;
  2415 000058C2 883D[77630000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2416                              <1> sndc8:
  2417 000058C8 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2418                              <1> sndc9:
  2419                              <1> 	; AL = Line status, AH = Modem status
  2420 000058C9 C3                  <1> 	retn
  2421                              <1> 
  2422                              <1> get_cpos:
  2423                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2424                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2425                              <1> 	;
  2426                              <1> 	; INPUT -> bl = video page number
  2427                              <1> 	; RETURN -> dx = cursor position
  2428                              <1> 
  2429 000058CA 53                  <1> 	push	ebx
  2430 000058CB 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2431 000058CE D0E3                <1> 	shl	bl, 1
  2432 000058D0 81C3[26630000]      <1> 	add	ebx, cursor_posn
  2433 000058D6 668B13              <1> 	mov	dx, [ebx]
  2434 000058D9 5B                  <1> 	pop	ebx
  2435 000058DA C3                  <1> 	retn
  2436                              <1> 
  2437                              <1> read_ac_current:
  2438                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2439                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2440                              <1> 	;
  2441                              <1> 	; INPUT -> bl = video page number
  2442                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2443                              <1> 
  2444 000058DB E842BCFFFF          <1> 	call 	find_position ; 'video.inc'
  2445                              <1> 	; dx = status port
  2446                              <1> 	; esi = cursor location/address
  2447 000058E0 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2448 000058E6 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2449 000058E9 C3                  <1> 	retn
  2450                              <1> 
  2451                              <1> syssleep:
  2452                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2453                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2454                              <1> 	;
  2455                              <1> 	; Retro UNIX 8086 v1 feature only
  2456                              <1> 	; (INPUT -> none)
  2457                              <1> 	;
  2458 000058EA 0FB61D[11670000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2459 000058F1 8AA3[23640000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2460 000058F7 E841EEFFFF          <1> 	call	sleep
  2461 000058FC E927D9FFFF          <1> 	jmp	sysret
  2462                              <1> 
  2463                              <1> 	; 27/02/2022
  2464                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2465                              <1> %if 0
  2466                              <1> 
  2467                              <1> vp_clr:
  2468                              <1> 	; Reset/Clear Video Page
  2469                              <1> 	;
  2470                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2471                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2472                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2473                              <1> 	;
  2474                              <1> 	; Retro UNIX 8086 v1 feature only !
  2475                              <1> 	;
  2476                              <1> 	; INPUTS -> 
  2477                              <1> 	;   BL = video page number	 
  2478                              <1> 	;
  2479                              <1> 	; OUTPUT ->
  2480                              <1> 	;   none
  2481                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2482                              <1> 	;
  2483                              <1> 	; 04/12/2013
  2484                              <1> 	sub	al, al
  2485                              <1> 	; al = 0 (clear video page)
  2486                              <1> 	; bl = video page
  2487                              <1> 	mov	ah, 07h
  2488                              <1> 	; ah = 7 (attribute/color)
  2489                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2490                              <1> 	; 24/12/2021
  2491                              <1> 	xor	ecx, ecx
  2492                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2493                              <1> 	call	scroll_up
  2494                              <1> 	; bl = video page
  2495                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2496                              <1> 	; 24/12/2021
  2497                              <1> 	xor	edx, edx 
  2498                              <1> 	jmp 	set_cpos
  2499                              <1> 
  2500                              <1> %endif
  2501                              <1> 
  2502                              <1> sysmsg:
  2503                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2504                              <1> 	; 11/11/2015
  2505                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2506                              <1> 	; Print user-application message on user's console tty
  2507                              <1> 	;
  2508                              <1> 	; Input -> EBX = Message address
  2509                              <1> 	;	   ECX = Message length (max. 255)
  2510                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2511                              <1> 	;
  2512 00005901 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2513                              <1> 	;ja	sysret ; nothing to do with big message size
  2514 00005907 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2515 00005909 08C9                <1> 	or	cl, cl
  2516                              <1> 	;jz	sysret
  2517 0000590B 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2518 0000590D 20D2                <1> 	and	dl, dl
  2519 0000590F 7502                <1> 	jnz	short sysmsg0
  2520 00005911 B207                <1> 	mov	dl, 07h ; default color
  2521                              <1> 		; (black background, light gray character)
  2522                              <1> sysmsg0:
  2523 00005913 891D[E8660000]      <1> 	mov	[u.base], ebx
  2524 00005919 8815[37630000]      <1> 	mov	[ccolor], dl ; color attributes
  2525 0000591F 89E5                <1> 	mov	ebp, esp
  2526 00005921 31DB                <1> 	xor	ebx, ebx ; 0
  2527 00005923 891D[F0660000]      <1> 	mov	[u.nread], ebx ; 0
  2528                              <1> 	;
  2529 00005929 381D[29670000]      <1> 	cmp	[u.kcall], bl ; 0
  2530 0000592F 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2531                              <1> 	;
  2532 00005931 890D[EC660000]      <1> 	mov	[u.count], ecx
  2533 00005937 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2534                              <1> 	; 24/12/2021
  2535                              <1> 	; (dword alignment for esp)
  2536 00005938 F6C103              <1> 	test	cl, 3
  2537 0000593B 7404                <1> 	jz	short sysmsg_7
  2538 0000593D 80C903              <1> 	or	cl, 3
  2539 00005940 41                  <1> 	inc	ecx
  2540                              <1> sysmsg_7:
  2541 00005941 29CC                <1> 	sub	esp, ecx
  2542 00005943 89E7                <1> 	mov	edi, esp
  2543 00005945 89E6                <1> 	mov	esi, esp
  2544 00005947 66891D[27670000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2545                              <1> 	; 11/11/2015
  2546 0000594E 8A25[F8660000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2547                              <1> 	; 0 = none
  2548 00005954 FECC                <1> 	dec	ah
  2549 00005956 790C                <1> 	jns	short sysmsg1 
  2550 00005958 8A1D[11670000]      <1> 	mov	bl, [u.uno] ; process number	
  2551 0000595E 8AA3[23640000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2552                              <1> sysmsg1:
  2553 00005964 8825[16670000]      <1> 	mov	[u.ttyn], ah
  2554                              <1> sysmsg2:
  2555 0000596A E89BF5FFFF          <1> 	call	cpass
  2556 0000596F 7416                <1> 	jz	short sysmsg5
  2557 00005971 AA                  <1> 	stosb
  2558 00005972 20C0                <1> 	and	al, al
  2559 00005974 75F4                <1> 	jnz	short sysmsg2
  2560                              <1> sysmsg3:
  2561 00005976 80FC07              <1> 	cmp	ah, 7 ; tty number
  2562 00005979 7711                <1> 	ja	short sysmsg6 ; serial port
  2563 0000597B E83E000000          <1> 	call	print_cmsg
  2564                              <1> sysmsg4:
  2565 00005980 89EC                <1> 	mov	esp, ebp	
  2566                              <1> sysmsg8: ; 24/12/2021	
  2567 00005982 E9A1D8FFFF          <1> 	jmp	sysret
  2568                              <1> sysmsg5:
  2569 00005987 C60700              <1> 	mov	byte [edi], 0
  2570 0000598A EBEA                <1> 	jmp	short sysmsg3
  2571                              <1> sysmsg6:
  2572 0000598C 8A06                <1> 	mov	al, [esi]
  2573 0000598E E843FEFFFF          <1> 	call	sndc
  2574 00005993 72EB                <1> 	jc	short sysmsg4
  2575 00005995 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2576 00005998 76E6                <1> 	jna	short sysmsg4
  2577 0000599A 46                  <1> 	inc 	esi
  2578 0000599B 8A25[16670000]      <1> 	mov	ah, [u.ttyn]
  2579 000059A1 EBE9                <1> 	jmp	short sysmsg6
  2580                              <1> 
  2581                              <1> sysmsgk: ; Temporary (01/07/2015)
  2582                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2583                              <1> 	; (ECX -character count- will not be considered)
  2584 000059A3 8B35[E8660000]      <1> 	mov	esi, [u.base]
  2585 000059A9 8A25[36630000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2586 000059AF 8825[16670000]      <1> 	mov	[u.ttyn], ah
  2587 000059B5 C605[29670000]00    <1> 	mov	byte [u.kcall], 0
  2588 000059BC EBB8                <1> 	jmp	short sysmsg3
  2589                              <1> 	
  2590                              <1> print_cmsg: 
  2591                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2592                              <1> 	;
  2593                              <1> 	; print message (on user's console tty) 
  2594                              <1> 	;	with requested color
  2595                              <1> 	;
  2596                              <1> 	; INPUTS:
  2597                              <1> 	;	esi = message address
  2598                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2599                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2600                              <1> 	;
  2601 000059BE AC                  <1> 	lodsb
  2602                              <1> pcmsg1:
  2603 000059BF 56                  <1> 	push 	esi
  2604 000059C0 0FB61D[16670000]    <1>         movzx   ebx, byte [u.ttyn]
  2605 000059C7 8A25[37630000]      <1> 	mov	ah, [ccolor]
  2606 000059CD E8EAB9FFFF          <1> 	call 	write_tty
  2607 000059D2 5E                  <1> 	pop	esi
  2608 000059D3 AC                  <1> 	lodsb
  2609 000059D4 20C0                <1> 	and 	al, al  ; 0
  2610 000059D6 75E7                <1> 	jnz 	short pcmsg1
  2611 000059D8 C3                  <1> 	retn
  2612                              <1> 
  2613                              <1> sysgeterr:
  2614                              <1> 	; 16/02/2022
  2615                              <1> 	; 09/12/2015
  2616                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2617                              <1> 	; Get last error number or page fault count
  2618                              <1> 	; (for debugging)
  2619                              <1> 	;
  2620                              <1> 	; Input -> EBX = return type
  2621                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2622                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2623                              <1> 	;	   FFFFFFFEh = total page fault count
  2624                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2625                              <1> 	;
  2626                              <1> 	; Output -> EAX = last error number or page fault count
  2627                              <1> 	;	   (depending on EBX input)
  2628                              <1> 	; 	
  2629 000059D9 21DB                <1> 	and 	ebx, ebx
  2630 000059DB 750F                <1> 	jnz	short glerr_2
  2631                              <1> glerr_0:
  2632 000059DD A1[17670000]        <1> 	mov	eax, [u.error]
  2633                              <1> glerr_1:
  2634 000059E2 A3[C8660000]        <1> 	mov	[u.r0], eax
  2635                              <1>  	;retn
  2636                              <1> 	; 16/02/2022 (BugFix)
  2637 000059E7 E93CD8FFFF          <1> 	jmp	sysret
  2638                              <1> glerr_2:
  2639 000059EC 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2640 000059ED 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2641 000059EF 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2642 000059F0 75EB                <1> 	jnz	short glerr_0
  2643 000059F2 A1[BC630000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2644 000059F7 EBE9                <1>         jmp     short glerr_1
  2645                              <1> glerr_3:
  2646 000059F9 A1[2B670000]        <1> 	mov 	eax, [u.pfcount]
  2647 000059FE EBE2                <1> 	jmp	short glerr_1
  2648                              <1> 
  2649                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2650                              <1> ;	     - PRINTER BIOS (Functions)		
  2651                              <1> 
  2652                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2653                              <1> ;
  2654                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2655                              <1> ; PRINTER_IO								       :
  2656                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2657                              <1> ; INPUT 								       :
  2658                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2659                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2660                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2661                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2662                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2663                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2664                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2665                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2666                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2667                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2668                              <1> ;		   |	   |	   |	   |	   |			       :
  2669                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2670                              <1> ;		   |	   |	   |	   |				       :
  2671                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2672                              <1> ;		   |	   |	   |					       :
  2673                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2674                              <1> ;		   |	   |						       :
  2675                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2676                              <1> ;		   |							       :
  2677                              <1> ;		   |_ 1 = NOT BUSY					       :
  2678                              <1> ;									       :
  2679                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2680                              <1> ;		IN @PRINTER_BASE AREA					       :
  2681                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2682                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2683                              <1> ;									       :
  2684                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2685                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2686                              <1> ;									       :
  2687                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2688                              <1> ;		ALL OTHERS UNCHANGED					       :
  2689                              <1> ;-------------------------------------------------------------------------------
  2690                              <1> 
  2691                              <1> int17h:
  2692                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2693                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2694                              <1> 	;
  2695                              <1> 	; (Default printer port: 378h) ; LPT1
  2696                              <1> 	; (Number of printers = 1)
  2697                              <1> 	
  2698                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2699                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2700                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2701                              <1> 
  2702                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2703                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2704                              <1> 
  2705                              <1> 	; INPUT:
  2706                              <1> 	;	ah = 0 -> print the character in AL 
  2707                              <1> 	;		 (sys write with write count >0)
  2708                              <1> 	;	ah = 1 -> initialize printer port
  2709                              <1> 	;		 (sys open)	
  2710                              <1> 	;	ah = 2 -> read the printer status 
  2711                              <1> 	;		 (sys write with write count = 0)
  2712                              <1> 	; OUTPUT:
  2713                              <1> 	;	ah = printer status
  2714                              <1> 
  2715                              <1> 	; Modified registers: eax, ecx, edx
  2716                              <1> 
  2717                              <1> PRINTER_IO_1:
  2718 00005A00 08E4                <1> 	or	ah, ah
  2719 00005A02 7417                <1> 	jz	short _b20
  2720 00005A04 FECC                <1> 	dec	ah
  2721 00005A06 7444                <1> 	jz	short _b80
  2722                              <1> 	;dec 	ah
  2723                              <1> 	;jz	short _b50
  2724                              <1> _b50:
  2725                              <1> 	;-----	PRINTER STATUS
  2726                              <1> B50:
  2727 00005A08 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2728                              <1> B60:
  2729 00005A09 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2730                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2731                              <1> 				; POINT TO CONTROL PORT
  2732 00005A0D EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2733 00005A0E EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2734 00005A0F 88C4                <1> 	mov	ah, al		; SAVE
  2735 00005A11 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2736                              <1> B70:
  2737 00005A14 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2738 00005A15 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2739 00005A17 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2740                              <1> B10:
  2741 00005A1A C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2742                              <1> _b20:
  2743                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2744 00005A1B B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2745                              <1> B20:
  2746 00005A20 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2747 00005A21 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2748 00005A25 EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2749 00005A26 FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2750                              <1> 
  2751                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2752                              <1> B25:
  2753                              <1> 	;-----	WAIT BUSY
  2754                              <1> B35:
  2755 00005A28 EC                  <1> 	in	al, dx		; GET STATUS
  2756 00005A29 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2757 00005A2B A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2758 00005A2D 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2759 00005A2F E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2760 00005A34 E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2761                              <1> 
  2762 00005A36 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2763 00005A39 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2764 00005A3C EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2765                              <1> 
  2766                              <1> B40:				; SEND STROBE PULSE
  2767 00005A3E B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2768 00005A40 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2769 00005A42 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2770 00005A43 EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2771                              <1> 	; IODELAY
  2772                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2773                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2774                              <1> 	; NEWIODELAY
  2775 00005A44 E6EB                <1> 	out	0EBh, al
  2776                              <1> 
  2777 00005A46 B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2778 00005A48 EE                  <1> 	out	dx, al
  2779 00005A49 FB                  <1> 	sti			; INTERRUPTS BACK ON
  2780                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2781                              <1> 	;jmp	short B50
  2782 00005A4A EBBD                <1> 	jmp	short B60
  2783                              <1> 
  2784                              <1> _b80:
  2785                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2786                              <1> B80:
  2787 00005A4C 50                  <1> 	push	eax		; SAVE (AL)
  2788 00005A4D 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2789 00005A51 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2790 00005A53 EE                  <1> 	out	dx, al
  2791                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2792 00005A54 B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2793                              <1> B90:				; INIT_LOOP
  2794                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2795                              <1> 	;jnz	short B90	; INIT_LOOP
  2796 00005A59 E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2797 00005A5E E2F9                <1> 	loop	B90	
  2798 00005A60 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2799 00005A62 EE                  <1> 	out	dx, al
  2800 00005A63 EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2801                              <1> 
  2802                              <1> 
  2803                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2804                              <1> ; -------------------------------------------------------------------
  2805                              <1> ;
  2806                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2807                              <1> ;;65536/30 = 2185
  2808                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2809                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2810                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2811                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2812                              <1> ;
  2813                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2814                              <1> ;
  2815                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2816                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2817                              <1> ;;1,080,000 / 30 = 36,000
  2818                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2819                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2820                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2821                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2822                              <1> ;
  2823                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2824                              <1> 
  2825                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2826                              <1> ; ------------------------------------------
  2827                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2828                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2829                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2830                              <1> ;	OUTPUT: BX:CX destroyed.
  2831                              <1> ;
  2832                              <1> ;	SAVES:	AX (except when NO STACK)
  2833                              <1> ;
  2834                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2835                              <1> ;		used this way, AX is assumed to be destroyed.
  2836                              <1> 
  2837                              <1> WAIT_REFRESH:
  2838                              <1> 	; 13/06/2022
  2839                              <1> 	; Modified for Retro UNIX 386 v1
  2840                              <1> 	
  2841                              <1> 	; (wait for 30 micro seconds)
  2842                              <1> 
  2843                              <1> 	SYS1	equ 61h ; PORT_B
  2844                              <1> 
  2845                              <1> WR_SHORT:
  2846 00005A65 50                  <1> 	push	eax
  2847                              <1> WR_STAT_0:
  2848 00005A66 E461                <1> 	in	al, SYS1	; wait for high to low
  2849 00005A68 A810                <1> 	test	al, 10h		; transition on memory
  2850 00005A6A 75FA                <1> 	jnz	short WR_STAT_0 
  2851                              <1> WR_STAT_1:
  2852 00005A6C E461                <1> 	in	al, SYS1
  2853 00005A6E A810                <1> 	test	al, 10h
  2854 00005A70 74FA                <1> 	jz	short WR_STAT_1
  2855 00005A72 58                  <1> 	pop	eax
  2856 00005A73 C3                  <1> 	retn
  2058                                  
  2059                                  ; 07/03/2015
  2060                                  ; Temporary Code
  2061                                  display_disks:
  2062 00005A74 803D[2C5E0000]00        	cmp 	byte [fd0_type], 0
  2063 00005A7B 7605                    	jna 	short ddsks1
  2064 00005A7D E87D000000              	call	pdskm
  2065                                  ddsks1:
  2066 00005A82 803D[2D5E0000]00        	cmp	byte [fd1_type], 0
  2067 00005A89 760C                    	jna	short ddsks2
  2068 00005A8B C605[F15F0000]31        	mov	byte [dskx], '1'
  2069 00005A92 E868000000              	call	pdskm
  2070                                  ddsks2:
  2071 00005A97 803D[2E5E0000]00        	cmp	byte [hd0_type], 0
  2072 00005A9E 7654                    	jna	short ddsk6
  2073 00005AA0 66C705[EF5F0000]68-     	mov	word [dsktype], 'hd'
  2073 00005AA8 64                 
  2074 00005AA9 C605[F15F0000]30        	mov	byte [dskx], '0'
  2075 00005AB0 E84A000000              	call	pdskm
  2076                                  ddsks3:
  2077 00005AB5 803D[2F5E0000]00        	cmp	byte [hd1_type], 0
  2078 00005ABC 7636                    	jna	short ddsk6
  2079 00005ABE C605[F15F0000]31        	mov	byte [dskx], '1'
  2080 00005AC5 E835000000              	call	pdskm
  2081                                  ddsks4:
  2082 00005ACA 803D[305E0000]00        	cmp	byte [hd2_type], 0
  2083 00005AD1 7621                    	jna	short ddsk6
  2084 00005AD3 C605[F15F0000]32        	mov	byte [dskx], '2'
  2085 00005ADA E820000000              	call	pdskm
  2086                                  ddsks5:
  2087 00005ADF 803D[315E0000]00        	cmp	byte [hd3_type], 0
  2088 00005AE6 760C                    	jna	short ddsk6
  2089 00005AE8 C605[F15F0000]33        	mov	byte [dskx], '3'
  2090 00005AEF E80B000000              	call	pdskm
  2091                                  ddsk6:
  2092 00005AF4 BE[00600000]            	mov	esi, nextline
  2093 00005AF9 E806000000              	call	pdskml
  2094                                  pdskm_ok:
  2095 00005AFE C3                      	retn
  2096                                  pdskm:
  2097 00005AFF BE[ED5F0000]            	mov	esi, dsk_ready_msg
  2098                                  pdskml:	
  2099 00005B04 AC                      	lodsb
  2100 00005B05 08C0                    	or	al, al
  2101 00005B07 74F5                    	jz	short pdskm_ok
  2102 00005B09 56                      	push	esi
  2103 00005B0A 31DB                    	xor	ebx, ebx ; 0
  2104                                  			; Video page 0 (bl=0)
  2105 00005B0C B407                    	mov	ah, 07h ; Black background, 
  2106                                  			; light gray forecolor
  2107 00005B0E E8A9B8FFFF              	call	write_tty
  2108 00005B13 5E                      	pop	esi
  2109 00005B14 EBEE                    	jmp	short pdskml
  2110                                  
  2111 00005B16 90<rep Ah>              align 16
  2112                                  
  2113                                  gdt:	; Global Descriptor Table
  2114                                  	; (30/07/2015, conforming cs)
  2115                                  	; (26/03/2015)
  2116                                  	; (24/03/2015, tss)
  2117                                  	; (19/03/2015)
  2118                                  	; (29/12/2013)
  2119                                  	;
  2120 00005B20 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2121                                  	; 18/08/2014
  2122                                  			; 8h kernel code segment, base = 00000000h		
  2123 00005B28 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2124                                  			; 10h kernel data segment, base = 00000000h	
  2125 00005B30 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2126                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2127 00005B38 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2128                                  			; 23h user data segment, base address = 400000h ; CORE
  2129 00005B40 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2130                                  			; Task State Segment
  2131 00005B48 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2132                                  			       ;  no IO permission in ring 3)
  2133                                  gdt_tss0:
  2134 00005B4A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2135                                  gdt_tss1:
  2136 00005B4C 00                      	db 0  ; TSS base address, bits 16-23 
  2137                                  	      		; 49h	
  2138 00005B4D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2139 00005B4E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2140                                  gdt_tss2:
  2141 00005B4F 00                      	db 0  ; TSS base address, bits 24-31 
  2142                                  
  2143                                  gdt_end:
  2144                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2145                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2146                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2147                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2148                                  
  2149                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2150                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2151                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2152                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2153                                  		; W= Writeable, A= Accessed
  2154                                  	
  2155                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2156                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2157                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2158                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2159                                  
  2160                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2161                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2162                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2163                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2164                                  	
  2165                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2166                                  
  2167                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2168                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2169                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2170                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2171                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2172                                  		; AVL= Available to programmers	
  2173                                  
  2174                                  gdtd:
  2175 00005B50 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2176 00005B52 [205B0000]                      dd gdt			; Address of the GDT
  2177                                  
  2178                                  	; 20/08/2014
  2179                                  idtd:
  2180 00005B56 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2181 00005B58 [A0600000]                      dd idt			; Address of the IDT
  2182                                  
  2183                                  Align 4
  2184                                  
  2185                                  	; 21/08/2014
  2186                                  ilist:
  2187                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2188                                  	;
  2189                                  	; Exception list
  2190                                  	; 25/08/2014	
  2191 00005B5C [1D080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2192 00005B60 [24080000]              	dd	exc1	
  2193 00005B64 [2B080000]              	dd 	exc2	
  2194 00005B68 [32080000]              	dd	exc3	
  2195 00005B6C [36080000]              	dd	exc4	
  2196 00005B70 [3A080000]              	dd	exc5	
  2197 00005B74 [3E080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2198 00005B78 [42080000]              	dd	exc7	
  2199 00005B7C [46080000]              	dd	exc8	
  2200 00005B80 [4A080000]              	dd	exc9	
  2201 00005B84 [4E080000]              	dd 	exc10	
  2202 00005B88 [52080000]              	dd	exc11
  2203 00005B8C [56080000]              	dd	exc12
  2204 00005B90 [5A080000]              	dd	exc13	; 0Dh, General Protection Fault
  2205 00005B94 [5E080000]              	dd 	exc14	; 0Eh, Page Fault
  2206 00005B98 [62080000]              	dd	exc15
  2207 00005B9C [66080000]              	dd	exc16
  2208 00005BA0 [6A080000]              	dd	exc17
  2209 00005BA4 [6E080000]              	dd 	exc18
  2210 00005BA8 [72080000]              	dd	exc19
  2211 00005BAC [76080000]              	dd 	exc20
  2212 00005BB0 [7A080000]              	dd	exc21
  2213 00005BB4 [7E080000]              	dd	exc22
  2214 00005BB8 [82080000]              	dd	exc23
  2215 00005BBC [86080000]              	dd 	exc24
  2216 00005BC0 [8A080000]              	dd	exc25
  2217 00005BC4 [8E080000]              	dd	exc26
  2218 00005BC8 [92080000]              	dd	exc27
  2219 00005BCC [96080000]              	dd 	exc28
  2220 00005BD0 [9A080000]              	dd	exc29
  2221 00005BD4 [9E080000]              	dd 	exc30
  2222 00005BD8 [A2080000]              	dd	exc31
  2223                                  	; Interrupt list
  2224 00005BDC [59060000]              	dd	timer_int	; INT 20h
  2225                                  		;dd	irq0	
  2226 00005BE0 [5E0B0000]              	dd	keyb_int	; 27/08/2014
  2227                                  		;dd	irq1
  2228 00005BE4 [77070000]              	dd	irq2
  2229                                  		; COM2 int
  2230 00005BE8 [7B070000]              	dd	irq3
  2231                                  		; COM1 int
  2232 00005BEC [86070000]              	dd	irq4
  2233 00005BF0 [91070000]              	dd	irq5
  2234                                  ;DISKETTE_INT: ;06/02/2015
  2235 00005BF4 [F61F0000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2236                                  		;dd	irq6
  2237                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2238                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2239 00005BF8 [0D0B0000]              	dd	default_irq7	; 25/02/2015
  2240                                  		;dd	irq7
  2241                                  ; Real Time Clock Interrupt
  2242 00005BFC [AB090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2243                                  		;dd	irq8	; INT 28h
  2244 00005C00 [A1070000]              	dd	irq9
  2245 00005C04 [A5070000]              	dd	irq10
  2246 00005C08 [A9070000]              	dd	irq11
  2247 00005C0C [AD070000]              	dd	irq12
  2248 00005C10 [B1070000]              	dd	irq13
  2249                                  ;HDISK_INT1:  ;06/02/2015 	
  2250 00005C14 [BA240000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2251                                  		;dd	irq14
  2252                                  ;HDISK_INT2:  ;06/02/2015
  2253 00005C18 [DD240000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2254                                  		;dd	irq15	; INT 2Fh
  2255                                  		; 14/08/2015
  2256 00005C1C [10310000]              	dd	sysent		; INT 30h (system calls)
  2257                                  	
  2258                                  	;dd	ignore_int
  2259 00005C20 00000000                	dd	0
  2260                                  
  2261                                  ;;;
  2262                                  ;;; 11/03/2015
  2263                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2264                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KYBDATA.INC
  2265                              <1> ; Last Modification: 13/06/2022
  2266                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2267                              <1> ;
  2268                              <1> ; ///////// KEYBOARD DATA ///////////////
  2269                              <1> 
  2270                              <1> ; 11/03/2015
  2271                              <1> ; 05/12/2014
  2272                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2273                              <1> ; 03/06/86  KEYBOARD BIOS
  2274                              <1> 
  2275                              <1> ;---------------------------------------------------------------------------------
  2276                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2277                              <1> ;---------------------------------------------------------------------------------
  2278                              <1> 
  2279                              <1> ;-----	TABLES FOR ALT CASE ------------
  2280                              <1> ;-----	ALT-INPUT-TABLE 
  2281 00005C24 524F50514B          <1> K30:	db	82,79,80,81,75
  2282 00005C29 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2283                              <1> ;-----	SUPER-SHIFT-TABLE 
  2284 00005C2E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2285 00005C34 161718191E1F        <1> 	db	22,23,24,25,30,31
  2286 00005C3A 202122232425        <1> 	db	32,33,34,35,36,37
  2287 00005C40 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2288 00005C46 3132                <1> 	db	49,50
  2289                              <1> 
  2290                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2291                              <1> ;-----	KEY_TABLE 
  2292 00005C48 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2293 00005C49 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2294 00005C4E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2295                              <1> _K6L    equ     $-_K6
  2296                              <1> 
  2297                              <1> ;-----	MASK_TABLE
  2298 00005C50 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2299 00005C51 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2300 00005C56 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2301                              <1> 
  2302                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2303 00005C58 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2304 00005C5E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2305                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2306 00005C64 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2307 00005C6A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2308 00005C70 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2309 00005C76 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2310 00005C7C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2311 00005C82 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2312 00005C88 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2313 00005C8E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2314                              <1> 	;				;----- FUNCTIONS ------		
  2315 00005C92 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2316 00005C98 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2317 00005C9E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2318 00005CA4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2319 00005CAA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2320                              <1> 
  2321                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2322 00005CB0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2322 00005CB9 39302D3D0809        <1>
  2323 00005CBF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2323 00005CC8 705B5D0DFF61736466- <1>
  2323 00005CD1 67686A6B6C3B27      <1>
  2324 00005CD8 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2324 00005CE1 6D2C2E2FFF2AFF20FF  <1>
  2325                              <1> ;-----	LC TABLE SCAN
  2326 00005CEA 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2327 00005CEF 4041424344          <1> 	db	64,65,66,67,68
  2328 00005CF4 FFFF                <1> 	db	-1,-1			; NL, SL
  2329                              <1> 
  2330                              <1> ;-----	KEYPAD TABLE
  2331 00005CF6 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2332 00005CFC 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2333 00005D03 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2334                              <1> 
  2335                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2336 00005D08 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2336 00005D11 28295F2B0800        <1>
  2337 00005D17 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2337 00005D20 507B7D0DFF41534446- <1>
  2337 00005D29 47484A4B4C3A22      <1>
  2338 00005D30 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2338 00005D39 4D3C3E3FFF2AFF20FF  <1>
  2339                              <1> ;-----	UC TABLE SCAN
  2340 00005D42 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2341 00005D47 595A5B5C5D          <1> 	db	89,90,91,92,93
  2342 00005D4C FFFF                <1> 	db	-1,-1			; NL, SL
  2343                              <1> 
  2344                              <1> ;-----	NUM STATE TABLE
  2345 00005D4E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2345 00005D57 3233302E            <1>
  2346                              <1> 	;
  2347 00005D5B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2348                              <1> 
  2349                              <1> Align	4
  2350                              <1> ;----------------------------------------
  2351                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2352                              <1> ;----------------------------------------
  2353 00005D60 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2354 00005D61 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2355                              <1> 				; (29h default setting for video mode 3)
  2356                              <1> 				; Mode Select register Bits
  2357                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2358                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2359                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2360                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2361                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2362                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2363                              <1> 				;   BIT 6, 7 - Not Used
  2364                              <1> 
  2365                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2366                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2367                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2368                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2369                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2370                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2371                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2372                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2373                              <1> ; Mode & 37h = Video signal OFF
  2374                              <1> 			
  2375                              <1> 
  2376                              <1> ; 26/08/2014
  2377                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2378                              <1> ; Derived from IBM "pc-at" 
  2379                              <1> ; rombios source code (06/10/1985)
  2380                              <1> ; 'dseg.inc'
  2381                              <1> 
  2382                              <1> ;---------------------------------------;
  2383                              <1> ;	SYSTEM DATA AREA		;
  2384                              <1> ;----------------------------------------
  2385 00005D62 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2386                              <1> 
  2387                              <1> ;----------------------------------------
  2388                              <1> ;	KEYBOARD DATA AREAS		;
  2389                              <1> ;----------------------------------------
  2390                              <1> 
  2391 00005D63 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2392 00005D64 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2393 00005D65 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2394 00005D66 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2395 00005D67 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2396 00005D68 [785D0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2397 00005D6C [985D0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2398 00005D70 [785D0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2399 00005D74 [785D0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2400                              <1> ; ------  HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY
  2401 00005D78 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2402                              <1> 
  2403                              <1> ; /// End Of KEYBOARD DATA ///
  2264                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2265                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2266                              <1> ; Last Modification: 11/03/2015
  2267                              <1> ;		    (Data section for 'VIDEO.INC')	
  2268                              <1> ;
  2269                              <1> ; ///////// VIDEO DATA ///////////////
  2270                              <1> 
  2271                              <1> video_params:
  2272                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2273                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2274                              <1> 	; VIDEO MODE 3
  2275 00005D98 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2276 00005D9F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2277 00005DA4 00000000            <1> 	db	0,0,0,0
  2278                              <1> 
  2279                              <1> ; /// End Of VIDEO DATA ///
  2265                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2266                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKDATA.INC
  2267                              <1> ; Last Modification: 12/07/2022
  2268                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2269                              <1> ;
  2270                              <1> ; *****************************************************************************
  2271                              <1> ; Ref: Retro UNIX 386 v1.1 'diskdata.inc' modification: 11/07/2022
  2272                              <1> 
  2273                              <1> ;----------------------------------------
  2274                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2275                              <1> ;	REFERENCED BY POST & BIOS	:
  2276                              <1> ;----------------------------------------
  2277                              <1> 
  2278 00005DA8 [0B5E0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2279                              <1> 
  2280                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2281                              <1> ;----------------------------------------------------------------
  2282                              <1> ; DISK_BASE							:
  2283                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2284                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2285                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2286                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2287                              <1> ;----------------------------------------------------------------
  2288                              <1> 
  2289                              <1> ;DISK_BASE:	
  2290                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2291                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2292                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2293                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2294                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2295                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2296                              <1> ;	DB	01BH		; GAP LENGTH
  2297                              <1> ;	DB	0FFH		; DTL
  2298                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2299                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2300                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2301                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2302                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2303                              <1> 
  2304                              <1> ;----------------------------------------
  2305                              <1> ;	ROM BIOS DATA AREAS		:
  2306                              <1> ;----------------------------------------
  2307                              <1> 
  2308                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2309                              <1> 
  2310                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2311                              <1> 
  2312                              <1> ;----------------------------------------
  2313                              <1> ;	DISKETTE DATA AREAS		:
  2314                              <1> ;----------------------------------------
  2315                              <1> 
  2316                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2317                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2318                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2319                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2320                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2321                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2322                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2323                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2324                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2325                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2326                              <1> 
  2327                              <1> ;----------------------------------------
  2328                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2329                              <1> ;----------------------------------------
  2330                              <1> 
  2331                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2332                              <1> 
  2333                              <1> ;----------------------------------------
  2334                              <1> ;	TIMER DATA AREA 		:
  2335                              <1> ;----------------------------------------
  2336                              <1> 
  2337                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2338                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2339                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2340                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2341                              <1> 
  2342                              <1> ;----------------------------------------
  2343                              <1> ;	ADDITIONAL MEDIA DATA		:
  2344                              <1> ;----------------------------------------
  2345                              <1> 
  2346                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2347                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2348                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2349                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2350                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2351                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2352                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2353                              <1> 
  2354                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2355                              <1> 
  2356                              <1> ;--------------------------------------------------------
  2357                              <1> ;	DRIVE TYPE TABLE				:
  2358                              <1> ;--------------------------------------------------------
  2359                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2360                              <1> DR_TYPE:
  2361 00005DAC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2362                              <1>                 ;DW      MD_TBL1
  2363 00005DAD [CA5D0000]          <1> 		dd	MD_TBL1
  2364 00005DB1 82                  <1> 		DB	02+BIT7ON
  2365                              <1> 		;DW      MD_TBL2
  2366 00005DB2 [D75D0000]          <1>                 dd      MD_TBL2
  2367 00005DB6 02                  <1> DR_DEFAULT:	DB	02
  2368                              <1>                 ;DW      MD_TBL3
  2369 00005DB7 [E45D0000]          <1> 		dd      MD_TBL3
  2370 00005DBB 03                  <1> 		DB	03
  2371                              <1>                 ;DW      MD_TBL4
  2372 00005DBC [F15D0000]          <1> 		dd      MD_TBL4
  2373 00005DC0 84                  <1> 		DB	04+BIT7ON
  2374                              <1>                 ;DW      MD_TBL5
  2375 00005DC1 [FE5D0000]          <1> 		dd      MD_TBL5
  2376 00005DC5 04                  <1> 		DB	04
  2377                              <1>                 ;DW      MD_TBL6
  2378 00005DC6 [0B5E0000]          <1> 		dd      MD_TBL6
  2379                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2380                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2381                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2382                              <1> ;--------------------------------------------------------
  2383                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2384                              <1> ;--------------------------------------------------------
  2385                              <1> ;--------------------------------------------------------
  2386                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2387                              <1> ;--------------------------------------------------------
  2388                              <1> MD_TBL1:        
  2389 00005DCA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2390 00005DCB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2391 00005DCC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2392 00005DCD 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2393 00005DCE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2394 00005DCF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2395 00005DD0 FF                  <1> 	DB	0FFH		; DTL
  2396 00005DD1 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2397 00005DD2 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2398 00005DD3 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2399 00005DD4 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2400 00005DD5 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2401 00005DD6 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2402                              <1> ;--------------------------------------------------------
  2403                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2404                              <1> ;--------------------------------------------------------
  2405                              <1> MD_TBL2:        
  2406 00005DD7 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2407 00005DD8 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2408 00005DD9 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2409 00005DDA 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2410 00005DDB 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2411 00005DDC 2A                  <1> 	DB	02AH		; GAP LENGTH
  2412 00005DDD FF                  <1> 	DB	0FFH		; DTL
  2413 00005DDE 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2414 00005DDF F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2415 00005DE0 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2416 00005DE1 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2417 00005DE2 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2418 00005DE3 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2419                              <1> ;--------------------------------------------------------
  2420                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2421                              <1> ;--------------------------------------------------------
  2422                              <1> MD_TBL3:
  2423 00005DE4 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2424 00005DE5 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2425 00005DE6 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2426 00005DE7 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2427 00005DE8 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2428 00005DE9 1B                  <1> 	DB	01BH		; GAP LENGTH
  2429 00005DEA FF                  <1> 	DB	0FFH		; DTL
  2430 00005DEB 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2431 00005DEC F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2432 00005DED 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2433 00005DEE 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2434 00005DEF 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2435 00005DF0 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2436                              <1> ;--------------------------------------------------------
  2437                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2438                              <1> ;--------------------------------------------------------
  2439                              <1> MD_TBL4:
  2440 00005DF1 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2441 00005DF2 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2442 00005DF3 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2443 00005DF4 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2444 00005DF5 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2445 00005DF6 2A                  <1> 	DB	02AH		; GAP LENGTH
  2446 00005DF7 FF                  <1> 	DB	0FFH		; DTL
  2447 00005DF8 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2448 00005DF9 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2449 00005DFA 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2450 00005DFB 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2451 00005DFC 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2452 00005DFD 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2453                              <1> ;--------------------------------------------------------
  2454                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2455                              <1> ;--------------------------------------------------------
  2456                              <1> MD_TBL5:
  2457 00005DFE DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2458 00005DFF 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2459 00005E00 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2460 00005E01 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2461 00005E02 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2462 00005E03 2A                  <1> 	DB	02AH		; GAP LENGTH
  2463 00005E04 FF                  <1> 	DB	0FFH		; DTL
  2464 00005E05 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2465 00005E06 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2466 00005E07 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2467 00005E08 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2468 00005E09 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2469 00005E0A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2470                              <1> ;--------------------------------------------------------
  2471                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2472                              <1> ;--------------------------------------------------------
  2473                              <1> MD_TBL6:
  2474 00005E0B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2475 00005E0C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2476 00005E0D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2477 00005E0E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2478 00005E0F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2479 00005E10 1B                  <1> 	DB	01BH		; GAP LENGTH
  2480 00005E11 FF                  <1> 	DB	0FFH		; DTL
  2481 00005E12 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2482 00005E13 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2483 00005E14 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2484 00005E15 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2485 00005E16 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2486 00005E17 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2487                              <1> 
  2488                              <1> 
  2489                              <1> ; << diskette.inc >>
  2490                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2491                              <1> ;
  2492                              <1> ;----------------------------------------
  2493                              <1> ;	ROM BIOS DATA AREAS		:
  2494                              <1> ;----------------------------------------
  2495                              <1> 
  2496                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2497                              <1> 
  2498                              <1> ;----------------------------------------
  2499                              <1> ;	FIXED DISK DATA AREAS		:
  2500                              <1> ;----------------------------------------
  2501                              <1> 
  2502                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2503                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2504                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2505                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2506                              <1> 
  2507                              <1> ;----------------------------------------
  2508                              <1> ;	ADDITIONAL MEDIA DATA		:
  2509                              <1> ;----------------------------------------
  2510                              <1> 
  2511                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2512                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2513                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2514                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2515                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2516                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2517                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2518                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2519                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2520                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2521                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2522                              <1> 
  2523                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2524                              <1> ;
  2525                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2526                              <1> 
  2527                              <1> ERR_TBL:
  2528 00005E18 E0                  <1> 	db	NO_ERR
  2529 00005E19 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2530 00005E1D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2531                              <1> 
  2532                              <1> ; 11/07/2022
  2533                              <1> ; 17/12/2014 (mov ax, [cfd])
  2534                              <1> ; 11/12/2014
  2535                              <1> ;cfd:		db 0			; current floppy drive (for GET_PARM)
  2536                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2537                              <1> ;pfd:		db 1			; previous floppy drive (for GET_PARM)
  2538                              <1> 					; (initial value of 'pfd 
  2539                              <1> 					; must be different then 'cfd' value
  2540                              <1> 					; to force updating/initializing
  2541                              <1> 					; current drive parameters) 
  2542                              <1> 
  2543                              <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2544 00005E21 FF                  <1> pfd:		db 0FFh
  2545                              <1> 
  2546                              <1> align 2
  2547                              <1> 
  2548 00005E22 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2549                              <1> 			      ; (170h)
  2550 00005E24 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2551                              <1> 
  2552                              <1> ; 05/01/2015 
  2553 00005E26 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2554                              <1> 
  2555                              <1> ; *****************************************************************************
  2266                                  ;;;
  2267                                  
  2268 00005E27 90                      Align 2
  2269                                  
  2270                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2271 00005E28 00                      boot_drv:    db 0 ; boot drive number (physical)
  2272                                  ; 24/11/2014
  2273 00005E29 00                      drv:	     db 0 
  2274 00005E2A 00                      last_drv:    db 0 ; last hdd
  2275 00005E2B 00                      hdc:         db 0  ; number of hard disk drives
  2276                                  		     ; (present/detected)
  2277                                  ;
  2278                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2279                                  ; Physical drive type & flags
  2280 00005E2C 00                      fd0_type:    db 0  ; floppy drive type
  2281 00005E2D 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2282                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2283                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2284                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2285                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2286 00005E2E 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2287 00005E2F 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2288 00005E30 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2289 00005E31 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2290                                  		     ; bit 0 - Fixed disk access subset supported
  2291                                  		     ; bit 1 - Drive locking and ejecting
  2292                                  		     ; bit 2 - Enhanced disk drive support
  2293                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2294                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2295                                  		     ; will interpret it as 'LBA ready'!)		
  2296                                  
  2297                                  ; 12/07/2022
  2298                                  ; (drv.cylinders, drv.spt, drv.spt will not be used now on)
  2299                                  ; ('diskio.inc')
  2300                                  ; ((spt and heads and cylinder counts will be taken from DPT))
  2301                                  
  2302                                  ; 11/03/2015 - 10/07/2015
  2303                                  ;drv.cylinders: dw 0,0,0,0,0,0,0
  2304                                  ;drv.heads:     dw 0,0,0,0,0,0,0
  2305                                  ;drv.spt:       dw 0,0,0,0,0,0,0
  2306                                  ; 12/07/2022 - 11/03/2015
  2307 00005E32 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2307 00005E3B 000000000000000000-
  2307 00005E44 000000000000000000-
  2307 00005E4D 00                 
  2308 00005E4E 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2309 00005E55 00000000000000          drv.error:     db 0,0,0,0,0,0,0
  2310                                  ;
  2311                                  
  2312                                  ; 27/08/2014
  2313                                  scr_row:
  2314 00005E5C E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2315                                  scr_col:
  2316 00005E60 00000000                	dd 0
  2317                                  
  2318                                  ;; 14/08/2015
  2319                                  ;;msgPM:
  2320                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2321                                  msgKVER:
  2322                                  	;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2323                                  	;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [29/04/2022]", 0	
  2324                                  	;;db "Retro UNIX 386 v1 - Kernel v0.2.0.19 [02/06/2022]", 0
  2325                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.20 [14/06/2022]", 0
  2326 00005E64 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.21 [12/07/2022]", 0
  2326 00005E6D 582033383620763120-
  2326 00005E76 2D204B65726E656C20-
  2326 00005E7F 76302E322E302E3231-
  2326 00005E88 205B31322F30372F32-
  2326 00005E91 3032325D00         
  2327                                  
  2328                                  Align 2
  2329                                  
  2330                                  ; 20/08/2014
  2331                                    ; /* This is the default interrupt "handler" :-) */ 
  2332                                    ; Linux v0.12 (head.s)
  2333                                  int_msg:
  2334 00005E96 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2334 00005E9F 6E7465727275707420-
  2334 00005EA8 212000             
  2335                                  
  2336 00005EAB 90                      Align 2  
  2337                                  
  2338                                  ; 21/08/2014
  2339                                  timer_msg:
  2340 00005EAC 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2340 00005EB5 542032306829202120-
  2340 00005EBE 54696D657220496E74-
  2340 00005EC7 657272757074203A20 
  2341                                  tcountstr:
  2342 00005ED0 303030303020            	db "00000 "
  2343 00005ED6 00                      	db 0
  2344                                  
  2345 00005ED7 90                      Align 2
  2346                                  	; 21/08/2014
  2347                                  exc_msg:
  2348 00005ED8 435055206578636570-     	db "CPU exception ! "
  2348 00005EE1 74696F6E202120     
  2349                                  excnstr: 		; 25/08/2014
  2350 00005EE8 3F3F68202045495020-     	db "??h", "  EIP : "
  2350 00005EF1 3A20               
  2351                                  EIPstr: ; 29/08/2014
  2352 00005EF3 00<rep Ch>              	times 12 db 0
  2353                                  rtc_msg:
  2354 00005EFF 5265616C2054696D65-     	db "Real Time Clock - "
  2354 00005F08 20436C6F636B202D20 
  2355                                  datestr:
  2356 00005F11 30302F30302F303030-     	db "00/00/0000"
  2356 00005F1A 30                 
  2357 00005F1B 20                      	db " "
  2358                                  daystr:
  2359 00005F1C 44415920                	db "DAY "
  2360                                  timestr:	
  2361 00005F20 30303A30303A3030                db "00:00:00"
  2362 00005F28 20                      	db " "
  2363 00005F29 00                      	db 0 
  2364                                  
  2365                                  daytmp:
  2366                                  	; 28/02/2015
  2367 00005F2A 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2367 00005F33 4F4E20545545205745-
  2367 00005F3C 442054485520465249-
  2367 00005F45 2053415420         
  2368                                  
  2369 00005F4A FF                      ptime_seconds: db 0FFh
  2370                                  
  2371                                  	; 23/02/2015
  2372                                  	; 25/08/2014
  2373                                  ;scounter:
  2374                                  ;	db 5
  2375                                  ;	db 19
  2376                                  
  2377                                  ;; 05/11/2014
  2378                                  ;msg_out_of_memory:
  2379                                  ;	db 	07h, 0Dh, 0Ah
  2380                                  ;	db      'Insufficient memory ! '
  2381                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2382                                  ; 	db	0Dh, 0Ah, 0
  2383                                  	;
  2384                                  setup_error_msg:
  2385 00005F4B 0D0A                    	db 0Dh, 0Ah
  2386 00005F4D 4469736B2053657475-     	db 'Disk Setup Error!' 
  2386 00005F56 70204572726F7221   
  2387 00005F5E 0D0A00                  	db 0Dh, 0Ah,0
  2388                                  
  2389                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2390                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2391                                  ;	  db 0 ; upper left row (for scroll)	
  2392                                  
  2393                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2394                                  ;	  db 24 ; lower right row (for scroll)
  2395                                  
  2396                                  
  2397                                  ; 06/11/2014 (Temporary Data)
  2398                                  ; Memory Information message
  2399                                  ; 14/08/2015
  2400                                  msg_memory_info:
  2401 00005F61 07                      	db	07h
  2402 00005F62 0D0A                    	db	0Dh, 0Ah
  2403                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2404 00005F64 546F74616C206D656D-     	db	"Total memory : "
  2404 00005F6D 6F7279203A20       
  2405                                  mem_total_b_str: ; 10 digits
  2406 00005F73 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2406 00005F7C 302062797465730D0A 
  2407 00005F85 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2407 00005F8E 202020202020202020 
  2408                                  mem_total_p_str: ; 7 digits
  2409 00005F97 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2409 00005FA0 616765730D0A       
  2410 00005FA6 0D0A                    	db 	0Dh, 0Ah
  2411 00005FA8 46726565206D656D6F-     	db	"Free memory  : "
  2411 00005FB1 727920203A20       
  2412                                  free_mem_b_str:  ; 10 digits
  2413 00005FB7 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2413 00005FC0 3F2062797465730D0A 
  2414 00005FC9 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2414 00005FD2 202020202020202020 
  2415                                  free_mem_p_str:  ; 7 digits
  2416 00005FDB 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2416 00005FE4 616765730D0A       
  2417 00005FEA 0D0A00                  	db	0Dh, 0Ah, 0
  2418                                  
  2419                                  dsk_ready_msg:
  2420 00005FED 0D0A                    	db 	0Dh, 0Ah
  2421                                  dsktype:
  2422 00005FEF 6664                    	db	'fd'
  2423                                  dskx:
  2424 00005FF1 30                      	db	'0'
  2425 00005FF2 20                      	db	20h
  2426 00005FF3 697320524541445920-     	db 	'is READY ...'
  2426 00005FFC 2E2E2E             
  2427 00005FFF 00                      	db 	0
  2428                                  nextline:
  2429 00006000 0D0A00                  	db 	0Dh, 0Ah, 0
  2430                                  
  2431                                  ; KERNEL - SYSINIT Messages
  2432                                  ; 24/08/2015
  2433                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2434                                  ; 14/07/2013
  2435                                  ;kernel_init_err_msg:
  2436                                  ;	db 0Dh, 0Ah
  2437                                  ;	db 07h
  2438                                  ;	db 'Kernel initialization ERROR !'
  2439                                  ;	db 0Dh, 0Ah, 0 
  2440                                  ; 24/08/2015
  2441                                  ;;; (temporary kernel init message has been removed
  2442                                  ;;;  from 'sys_init' code)
  2443                                  ;kernel_init_ok_msg: 
  2444                                  ;	db 0Dh, 0Ah
  2445                                  ;	db 07h
  2446                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2447                                  ;	db 0Dh, 0Ah
  2448                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2449                                  ;	db 0Dh, 0Ah, 0
  2450                                  panic_msg:
  2451 00006003 0D0A07                  	db 0Dh, 0Ah, 07h
  2452 00006006 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2452 0000600F 726E656C2050616E69-
  2452 00006018 632021             
  2453 0000601B 0D0A00                  	db 0Dh, 0Ah, 0
  2454                                  etc_init_err_msg:
  2455 0000601E 0D0A                    	db 0Dh, 0Ah
  2456 00006020 07                      	db 07h
  2457 00006021 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2457 0000602A 74632F696E69742021-
  2457 00006033 3F                 
  2458 00006034 0D0A00                  	db 0Dh, 0Ah, 0
  2459                                  
  2460                                  ; 10/05/2015
  2461                                  badsys_msg:
  2462 00006037 0D0A                    	db 0Dh, 0Ah
  2463 00006039 07                      	db 07h
  2464 0000603A 496E76616C69642053-     	db 'Invalid System Call !'
  2464 00006043 797374656D2043616C-
  2464 0000604C 6C2021             
  2465 0000604F 0D0A                    	db 0Dh, 0Ah
  2466 00006051 4541583A20              	db 'EAX: '
  2467                                  bsys_msg_eax:
  2468 00006056 303030303030303068      	db '00000000h'
  2469 0000605F 0D0A                    	db 0Dh, 0Ah
  2470 00006061 4549503A20              	db 'EIP: '
  2471                                  bsys_msg_eip:
  2472 00006066 303030303030303068      	db '00000000h' 
  2473 0000606F 0D0A00                  	db 0Dh, 0Ah, 0
  2474                                  
  2475                                  BSYS_M_SIZE equ $ - badsys_msg
  2476                                  
  2477                                  
  2478                                  align 2
  2479                                  
  2480                                  ; EPOCH Variables
  2481                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2482                                  ; 09/04/2013 epoch variables
  2483                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2484                                  ;
  2485 00006072 B207                    year: 	dw 1970
  2486                                  ;month: dw 1
  2487                                  ;day: 	dw 1
  2488                                  ;hour: 	dw 0
  2489                                  ;minute: dw 0
  2490                                  ;second: dw 0
  2491                                  ; 02/06/2022
  2492 00006074 01                      month:	db 1
  2493 00006075 01                      day:	db 1
  2494 00006076 01                      hour:	db 1
  2495 00006077 01                      minute: db 1
  2496 00006078 01                      second:	db 1
  2497 00006079 01                      	db 1
  2498                                  
  2499                                  DMonth:
  2500 0000607A 0000                    	dw 0
  2501 0000607C 1F00                    	dw 31
  2502 0000607E 3B00                    	dw 59
  2503 00006080 5A00                    	dw 90
  2504 00006082 7800                    	dw 120
  2505 00006084 9700                    	dw 151
  2506 00006086 B500                    	dw 181
  2507 00006088 D400                    	dw 212
  2508 0000608A F300                    	dw 243
  2509 0000608C 1101                    	dw 273
  2510 0000608E 3001                    	dw 304
  2511 00006090 4E01                    	dw 334
  2512                                  
  2513                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2514 00006092 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2515                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2516 00006094 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2517                                  		   ;   between 16 MB and 4 GB.
  2518                                  
  2519 00006096 90<rep Ah>              align 16
  2520                                  
  2521                                  bss_start:
  2522                                  
  2523                                  ABSOLUTE bss_start
  2524                                  
  2525                                  	; 11/03/2015
  2526                                  	; Interrupt Descriptor Table (20/08/2014)
  2527                                  idt:
  2528 000060A0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2529                                  idt_end:
  2530                                  
  2531                                  ;alignb 4
  2532                                  
  2533                                  task_state_segment:
  2534                                  	; 24/03/2015
  2535 000062A0 ????                    tss.link:   resw 1
  2536 000062A2 ????                    	    resw 1
  2537                                  ; tss offset 4	
  2538 000062A4 ????????                tss.esp0:   resd 1
  2539 000062A8 ????                    tss.ss0:    resw 1
  2540 000062AA ????                    	    resw 1	
  2541 000062AC ????????                tss.esp1:   resd 1
  2542 000062B0 ????                    tss.ss1:    resw 1
  2543 000062B2 ????                    	    resw 1 	
  2544 000062B4 ????????                tss.esp2:   resd 1
  2545 000062B8 ????                    tss.ss2:    resw 1
  2546 000062BA ????                    	    resw 1
  2547                                  ; tss offset 28
  2548 000062BC ????????                tss.CR3:    resd 1
  2549 000062C0 ????????                tss.eip:    resd 1
  2550 000062C4 ????????                tss.eflags: resd 1
  2551                                  ; tss offset 40
  2552 000062C8 ????????                tss.eax:    resd 1		 		
  2553 000062CC ????????                tss.ecx:    resd 1
  2554 000062D0 ????????                tss.edx:    resd 1
  2555 000062D4 ????????                tss.ebx:    resd 1
  2556 000062D8 ????????                tss.esp:    resd 1
  2557 000062DC ????????                tss.ebp:    resd 1
  2558 000062E0 ????????                tss.esi:    resd 1
  2559 000062E4 ????????                tss.edi:    resd 1
  2560                                  ; tss offset 72
  2561 000062E8 ????                    tss.ES:     resw 1
  2562 000062EA ????                    	    resw 1	
  2563 000062EC ????                    tss.CS:	    resw 1
  2564 000062EE ????                    	    resw 1
  2565 000062F0 ????                    tss.SS:	    resw 1
  2566 000062F2 ????                    	    resw 1
  2567 000062F4 ????                    tss.DS:	    resw 1
  2568 000062F6 ????                    	    resw 1
  2569 000062F8 ????                    tss.FS:	    resw 1
  2570 000062FA ????                    	    resw 1
  2571 000062FC ????                    tss.GS:	    resw 1
  2572 000062FE ????                    	    resw 1		
  2573 00006300 ????                    tss.LDTR:   resw 1
  2574 00006302 ????                    	    resw 1
  2575                                  ; tss offset 100		
  2576 00006304 ????                    	    resw 1		
  2577 00006306 ????                    tss.IOPB:   resw 1
  2578                                  ; tss offset 104 
  2579                                  tss_end:
  2580                                  
  2581 00006308 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2582                                  		    ; (Physical address = Virtual address)	 	
  2583 0000630C ????????                memory_size: resd 1 ; memory size in pages
  2584 00006310 ????????                free_pages:  resd 1 ; number of free pages		
  2585 00006314 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2586                                  		    ; first free page search
  2587 00006318 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2588                                  		    ; next free page search will be
  2589                                  		    ; stopped after it. (end of M.A.T.)
  2590 0000631C ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2591                                  		    ; first free page search
  2592                                  		    ; will be started on it. (for user)
  2593 00006320 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2594                                  
  2595                                  ;;;
  2596                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2597                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2598 00006324 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2599                                  		    ; NOTE: active page only
  2600 00006326 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2601                                  active_page: 
  2602 00006336 ??                      ptty: 	     resb 1 ; current tty
  2603                                  ; 01/07/2015
  2604 00006337 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2605                                  ; 26/10/2015
  2606                                  ; 07/09/2014
  2607 00006338 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2608                                  
  2609                                  ; 21/08/2014
  2610 0000634C ????????                tcount:	     resd 1
  2611                                  
  2612                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2613 00006350 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2614                                  
  2615                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2616                                  ; (open mode locks for pseudo TTYs)
  2617                                  ; [ major tty locks (return error in any conflicts) ]
  2618 00006354 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2619                                  
  2620                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2621                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2622 00006368 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2623                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2624                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2625                                  ;; 0 means serial port is not available 
  2626                                  ;;comprm: ; 25/06/2014
  2627 00006372 ??                      com1p:       resb 1 ;;0E3h
  2628 00006373 ??                      com2p:       resb 1 ;;0E3h
  2629                                  
  2630                                  ; 17/11/2015
  2631                                  ; request for response (from the terminal)	
  2632 00006374 ????                    req_resp:     resw 1 			
  2633                                  ; 07/11/2015
  2634 00006376 ??                      ccomport:    resb 1 ; current COM (serial) port
  2635                                  		    ; (0= COM1, 1= COM2)
  2636                                  ; 09/11/2015
  2637 00006377 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2638                                  ; 07/11/2015
  2639 00006378 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2640 0000637A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2641                                  
  2642                                  ; 23/10/2015
  2643                                  ; SERIAL PORTS - COMMUNICATION MODES
  2644                                  ; (Retro UNIX 386 v1 feature only!)
  2645                                  ; 0 - command mode (default/initial mode)
  2646                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2647                                  ;;; communication modes for future versions:  
  2648                                  ; // 2 - keyboard mode (ascii+scancode input)
  2649                                  ; // 3 - mouse mode
  2650                                  ; // 4 - device control (output) mode
  2651                                  ; VALID COMMANDS for current version:
  2652                                  ; 	'LOGIN'
  2653                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2654                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2655                                  ;  Login response: db 0FFh, 'login', 0
  2656                                  ;	 ("login request accepted, wait for login prompt") 
  2657                                  ; When a login requests is received and acknowledged (by
  2658                                  ; serial port interrupt handler (communication procedure),
  2659                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2660                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2661                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2662                                  ; 
  2663                                  ; 'sys connect' system call is used to change communication mode
  2664                                  ; except 'LOGIN' command which is used to start terminal mode
  2665                                  ; by using (COM port) terminal.
  2666                                  
  2667                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2668                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2669                                  ;com1mode:    resb 1 ; communication mode for COM1
  2670                                  ;com1com:     resb 1 ; communication command for COM1
  2671                                  ;com2mode:    resb 1 ; communication mode for COM1
  2672                                  ;com2com      resb 1 ; communication command for COM1
  2673                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2674                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2675                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2676                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2677                                  
  2678                                  ; 22/08/2014 (RTC)
  2679                                  ; (Packed BCD)
  2680 0000637C ??                      time_seconds: resb 1
  2681 0000637D ??                      time_minutes: resb 1
  2682 0000637E ??                      time_hours:   resb 1
  2683 0000637F ??                      date_wday:    resb 1
  2684 00006380 ??                      date_day:     resb 1
  2685 00006381 ??                      date_month:   resb 1			
  2686 00006382 ??                      date_year:    resb 1
  2687 00006383 ??                      date_century: resb 1
  2688                                  
  2689                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2690                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKBSS.INC
  2691                              <1> ; Last Modification: 12/07/2022
  2692                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC') 
  2693                              <1> ;
  2694                              <1> ; *****************************************************************************
  2695                              <1> ; Ref: Retro UNIX 386 v1.1 'disbss.inc' modification: 10/07/2022
  2696                              <1> 
  2697                              <1> 
  2698                              <1> alignb 2
  2699                              <1> 
  2700                              <1> ;----------------------------------------
  2701                              <1> ;	TIMER DATA AREA 		:
  2702                              <1> ;----------------------------------------
  2703                              <1> 
  2704                              <1> TIMER_LH:	; 16/02/205
  2705 00006384 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2706 00006386 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2707 00006388 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2708                              <1> 
  2709                              <1> ;----------------------------------------
  2710                              <1> ;	DISKETTE DATA AREAS		:
  2711                              <1> ;----------------------------------------
  2712                              <1> 
  2713 00006389 ??                  <1> SEEK_STATUS:	resb	1
  2714 0000638A ??                  <1> MOTOR_STATUS:	resb	1
  2715 0000638B ??                  <1> MOTOR_COUNT:	resb	1
  2716 0000638C ??                  <1> DSKETTE_STATUS:	resb	1
  2717 0000638D ??????????????      <1> NEC_STATUS:	resb	7
  2718                              <1> 
  2719                              <1> ;----------------------------------------
  2720                              <1> ;	ADDITIONAL MEDIA DATA		:
  2721                              <1> ;----------------------------------------
  2722                              <1> 
  2723 00006394 ??                  <1> LASTRATE:	resb 	1
  2724 00006395 ??                  <1> HF_STATUS:	resb 	1
  2725                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2726 00006396 ??                  <1> HF_INT_FLAG:	resb	1
  2727                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2728                              <1> ;DSK_STATE:	resb 	4
  2729 00006397 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2730 00006399 ????                <1> DSK_TRK:	resb 	2
  2731                              <1> 
  2732                              <1> ;----------------------------------------
  2733                              <1> ;	FIXED DISK DATA AREAS		:
  2734                              <1> ;----------------------------------------
  2735                              <1> 
  2736 0000639B ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2737 0000639C ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2738 0000639D ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2739                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2740                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2741                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2742                              <1> 
  2743 0000639E ????                <1> alignb 4
  2744                              <1> 
  2745                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2746                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2747                              <1> HF_TBL_VEC: ; 22/12/2014	
  2748 000063A0 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2749 000063A4 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2750 000063A8 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2751 000063AC ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2752                              <1> 
  2753                              <1> ; 03/01/2015
  2754 000063B0 ??                  <1> LBAMode:     	resb	1
  2755                              <1> 
  2756                              <1> ; *****************************************************************************
  2690                                  
  2691                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2692                                  
  2693                                  ;alignb 2
  2694                                  
  2695                                  ; 27/02/2022
  2696                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2697                                  
  2698                                  ; 23/02/2022
  2699                                  ;; Memory (swap) Data (11/03/2015)
  2700                                  ; 09/03/2015
  2701                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2702                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2703                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2704                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2705                                  ;swpd_next:  resd 1 ; next free page block
  2706                                  ;swpd_last:  resd 1 ; last swap page block	
  2707                                  
  2708 000063B1 ??????                  alignb 4
  2709                                  
  2710                                  ; 10/07/2015
  2711                                  ; 28/08/2014
  2712 000063B4 ????????                error_code:	resd 1
  2713                                  ; 29/08/2014
  2714 000063B8 ????????                FaultOffset: 	resd 1
  2715                                  ; 21/09/2015
  2716 000063BC ????????                PF_Count:	resd 1	; total page fault count
  2717                                  		       	; (for debugging - page fault analyze)
  2718                                  		 	; 'page _fault_handler' (memory.inc)
  2719                                  			; 'sysgeterr' (u9.s)
  2720                                  ; 23/02/2022
  2721 000063C0 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2722                                  			;  for a system call in next retro unix 386 version)
  2723                                  			; -2 ticks per second-
  2724                                  ;; 21/08/2015
  2725                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2726                                  
  2727                                  ; 27/02/2022
  2728                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2729                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYSX.INC (ux.s)
  2730                              <1> ; Last Modification: 14/05/2022
  2731                              <1> ;
  2732                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2733                              <1> ; (Modified from 
  2734                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2735                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2736                              <1> ; ----------------------------------------------------------------------------
  2737                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2738                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2739                              <1> ; <Bell Laboratories (17/3/1972)>
  2740                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2741                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2742                              <1> ; ****************************************************************************
  2743                              <1> ; 13/11/2015
  2744                              <1> 
  2745                              <1> alignb 2
  2746                              <1> 
  2747                              <1> inode:
  2748                              <1> 	; 11/03/2013. 
  2749                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2750                              <1> 	;i.
  2751                              <1> 
  2752 000063C4 ????                <1> 	i.flgs:	 resw 1
  2753 000063C6 ??                  <1> 	i.nlks:	 resb 1
  2754 000063C7 ??                  <1> 	i.uid:	 resb 1
  2755 000063C8 ????                <1>         i.size:  resw 1 ; size
  2756 000063CA <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2757 000063DA ????????            <1> 	i.ctim:	 resd 1
  2758 000063DE ????????            <1> 	i.mtim:	 resd 1
  2759 000063E2 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2760                              <1> 
  2761                              <1> I_SIZE	equ $ - inode 
  2762                              <1> 
  2763                              <1> process:
  2764                              <1> 	; 26/02/2022
  2765                              <1> 	; 04/02/2022
  2766                              <1> 	; 06/05/2015
  2767                              <1> 	; 11/03/2013 - 05/02/2014
  2768                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2769                              <1> 	;p.
  2770                              <1> 	
  2771 000063E4 <res 20h>           <1>         p.pid:   resw nproc
  2772 00006404 <res 20h>           <1>         p.ppid:  resw nproc
  2773                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2774 00006424 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2775                              <1> 	; 26/02/2022 (p.waitc is not used)
  2776                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2777 00006434 <res 10h>           <1> 	p.link:	 resb nproc
  2778 00006444 <res 10h>           <1> 	p.stat:	 resb nproc
  2779                              <1> 
  2780                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2781 00006454 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2782                              <1> 			    ; 'user' structure	
  2783                              <1> 
  2784                              <1> 
  2785                              <1> P_SIZE	equ $ - process
  2786                              <1> 
  2787                              <1> 
  2788                              <1> ; fsp table (original UNIX v1)
  2789                              <1> ;
  2790                              <1> ;Entry
  2791                              <1> ;          15                                      0
  2792                              <1> ;  1     |---|---------------------------------------|
  2793                              <1> ;        |r/w|       i-number of open file           |
  2794                              <1> ;        |---|---------------------------------------| 
  2795                              <1> ;        |               device number               |
  2796                              <1> ;        |-------------------------------------------|
  2797                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2798                              <1> ;        |-------------------------------------------| 
  2799                              <1> ;        |  flag that says    | number of processes  |
  2800                              <1> ;        |   file deleted     | that have file open  |
  2801                              <1> ;        |-------------------------------------------| 
  2802                              <1> ;  2     |                                           |
  2803                              <1> ;        |-------------------------------------------| 
  2804                              <1> ;        |                                           |
  2805                              <1> ;        |-------------------------------------------|
  2806                              <1> ;        |                                           |
  2807                              <1> ;        |-------------------------------------------|
  2808                              <1> ;        |                                           |
  2809                              <1> ;        |-------------------------------------------| 
  2810                              <1> ;  3     |                                           | 
  2811                              <1> ;        |                                           |  
  2812                              <1> ;
  2813                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2814                              <1> 
  2815                              <1> 
  2816                              <1> ; 15/04/2015
  2817 00006494 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2818 00006688 <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2819 000066A8 ????                <1> ii:	 resw 1
  2820 000066AA ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2821 000066AC ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2822                              <1> ; 18/05/2015
  2823                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2824                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2825                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2826                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2827                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2828                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2829                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2830                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2831                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2832                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2833                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2834 000066AE ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2835                              <1> 	        ; as above, for physical drives numbers in following table
  2836 000066AF ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2837                              <1> ; 15/04/2015
  2838 000066B0 ??                  <1> active:	 resb 1 
  2839 000066B1 ??                  <1> 	 resb 1 ; 09/06/2015
  2840 000066B2 ????                <1> mnti:	 resw 1
  2841 000066B4 ????                <1> mntp:	 resw 1 ; 14/05/2022 ; (parent dir inumber of [mnti])
  2842 000066B6 ????                <1> mpid:	 resw 1
  2843 000066B8 ????                <1> rootdir: resw 1
  2844                              <1> ; 14/02/2014
  2845                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2846                              <1> ;		      Single level run queue
  2847                              <1> ;		      (in order to solve sleep/wakeup lock)
  2848 000066BA ????                <1> runq:	 resw 1
  2849 000066BC ??                  <1> imod:	 resb 1
  2850 000066BD ??                  <1> smod:	 resb 1
  2851 000066BE ??                  <1> mmod:	 resb 1
  2852 000066BF ??                  <1> sysflg:	 resb 1
  2853                              <1> 
  2854                              <1> alignb 4
  2855                              <1> 
  2856                              <1> user:
  2857                              <1> 	; 18/10/2015
  2858                              <1> 	; 12/10/2015
  2859                              <1> 	; 21/09/2015
  2860                              <1> 	; 24/07/2015
  2861                              <1> 	; 16/06/2015
  2862                              <1> 	; 09/06/2015
  2863                              <1> 	; 11/05/2015
  2864                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2865                              <1> 	; 10/10/2013
  2866                              <1> 	; 11/03/2013. 
  2867                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2868                              <1> 	;u.
  2869                              <1> 
  2870 000066C0 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2871 000066C4 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2872 000066C8 ????????            <1> 	u.r0:	  resd 1 ; eax
  2873 000066CC ????                <1> 	u.cdir:	  resw 1
  2874 000066CE <res Ah>            <1> 	u.fp:	  resb 10
  2875 000066D8 ????????            <1> 	u.fofp:	  resd 1
  2876 000066DC ????????            <1> 	u.dirp:	  resd 1
  2877 000066E0 ????????            <1> 	u.namep:  resd 1
  2878 000066E4 ????????            <1> 	u.off:	  resd 1
  2879 000066E8 ????????            <1> 	u.base:	  resd 1
  2880 000066EC ????????            <1> 	u.count:  resd 1
  2881 000066F0 ????????            <1> 	u.nread:  resd 1
  2882 000066F4 ????????            <1> 	u.break:  resd 1 ; break
  2883 000066F8 ????                <1> 	u.ttyp:	  resw 1 
  2884 000066FA <res Ah>            <1> 	u.dirbuf: resb 10
  2885                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2886 00006704 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2887 00006705 ??                  <1> 	u.pri:	  resb 1 ; 
  2888 00006706 ????                <1> 	u.intr:	  resw 1
  2889 00006708 ????                <1> 	u.quit:	  resw 1
  2890                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2891 0000670A ????                <1> 	u.ilgins: resw 1
  2892 0000670C ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2893 0000670E ??                  <1> 	u.uid:	  resb 1 ; uid
  2894 0000670F ??                  <1> 	u.ruid:	  resb 1
  2895 00006710 ??                  <1> 	u.bsys:	  resb 1
  2896 00006711 ??                  <1> 	u.uno:	  resb 1
  2897 00006712 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2898                              <1> 	; tty number (rtty, rcvt, wtty)
  2899 00006716 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2900                              <1> 	; last error number
  2901 00006717 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2902                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2903 0000671B ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2904 0000671F ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2905 00006723 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2906 00006727 ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2907                              <1> 	;u.pncount: resw 1 
  2908                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2909                              <1> 	;u.pnbase:  resd 1 
  2910                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2911                              <1> 			 ; 09/06/2015
  2912 00006729 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2913 0000672A ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2914                              <1> 			 ; 24/07/2015 - 24/06/2015
  2915                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2916                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2917                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2918                              <1>  			 ; 24/06/2015	  	
  2919                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2920                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2921                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2922 0000672B ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2923                              <1> 
  2924 0000672F ??                  <1> alignb 4
  2925                              <1> 
  2926                              <1> U_SIZE	equ $ - user
  2927                              <1> 
  2928                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2929 00006730 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2930 00006734 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2931 00006738 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2932 0000673C ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2933 0000673E ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2934 00006740 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2935                              <1> 
  2936                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2937                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2938 00006744 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2939 00006745 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2940 00006746 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2941 00006747 ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2942                              <1> 
  2943                              <1> ;alignb 4
  2944                              <1> 
  2945                              <1> ; 22/08/2015
  2946 00006748 <res C30h>          <1> buffer: resb nbuf * 520
  2947                              <1> 
  2948 00007378 ????????????????    <1> sb0:	resd 2
  2949                              <1> ;s:
  2950                              <1> ; (root disk) super block buffer
  2951                              <1> systm:
  2952                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2953                              <1> 	; 11/03/2013. 
  2954                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2955                              <1> 	;s.
  2956                              <1> 
  2957 00007380 ????                <1> 	resw 1
  2958 00007382 <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2959 000074EA ????                <1> 	resw 1
  2960 000074EC <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2961                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2962 0000750C ????????            <1> 	s.time:	 resd 1
  2963 00007510 ????????            <1> 	s.syst:	 resd 1
  2964 00007514 ????????            <1>         s.wait_: resd 1 ; wait
  2965 00007518 ????????            <1> 	s.idlet: resd 1
  2966 0000751C ????????            <1> 	s.chrgt: resd 1
  2967 00007520 ????                <1> 	s.drerr: resw 1
  2968                              <1> 
  2969                              <1> S_SIZE	equ $ - systm
  2970                              <1> 
  2971 00007522 <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2972                              <1> 
  2973 00007580 ????????????????    <1> sb1:	resd 2
  2974                              <1> ; (mounted disk) super block buffer
  2975                              <1> mount:	
  2976 00007588 <res 200h>          <1> 	resb 512  ; 03/06/2015
  2977                              <1> 
  2978                              <1> ;/ ux -- unix
  2979                              <1> ;
  2980                              <1> ;systm:
  2981                              <1> ;
  2982                              <1> ;	.=.+2
  2983                              <1> ;	.=.+128.
  2984                              <1> ;	.=.+2
  2985                              <1> ;	.=.+64.
  2986                              <1> ;	s.time: .=.+4
  2987                              <1> ;	s.syst: .=.+4
  2988                              <1> ;	s.wait: .=.+4
  2989                              <1> ;	s.idlet:.=.+4
  2990                              <1> ;	s.chrgt:.=.+4
  2991                              <1> ;	s.drerr:.=.+2
  2992                              <1> ;inode:
  2993                              <1> ;	i.flgs: .=.+2
  2994                              <1> ;	i.nlks: .=.+1
  2995                              <1> ;	i.uid:  .=.+1
  2996                              <1> ;	i.size: .=.+2
  2997                              <1> ;	i.dskp: .=.+16.
  2998                              <1> ;	i.ctim: .=.+4
  2999                              <1> ;	i.mtim: .=.+4
  3000                              <1> ;	. = inode+32.
  3001                              <1> ;mount:	.=.+1024.
  3002                              <1> ;proc:
  3003                              <1> ;	p.pid:  .=.+[2*nproc]
  3004                              <1> ;	p.dska: .=.+[2*nproc]
  3005                              <1> ;	p.ppid: .=.+[2*nproc]
  3006                              <1> ;	p.break:.=.+[2*nproc]
  3007                              <1> ;	p.link: .=.+nproc
  3008                              <1> ;	p.stat: .=.+nproc
  3009                              <1> ;tty:
  3010                              <1> ;	. = .+[ntty*8.]
  3011                              <1> ;fsp:	.=.+[nfiles*8.]
  3012                              <1> ;bufp:	.=.+[nbuf*2]+6
  3013                              <1> ;sb0:	.=.+8
  3014                              <1> ;sb1:	.=.+8
  3015                              <1> ;swp:	.=.+8
  3016                              <1> ;ii:	.=.+2
  3017                              <1> ;idev:	.=.+2
  3018                              <1> ;cdev:	.=.+2
  3019                              <1> ;deverr: .=.+12.
  3020                              <1> ;active: .=.+2
  3021                              <1> ;rfap:	.=.+2
  3022                              <1> ;rkap:	.=.+2
  3023                              <1> ;tcap:	.=.+2
  3024                              <1> ;tcstate:.=.+2
  3025                              <1> ;tcerrc: .=.+2
  3026                              <1> ;mnti:	.=.+2
  3027                              <1> ;mntd:	.=.+2
  3028                              <1> ;mpid:	.=.+2
  3029                              <1> ;clockp: .=.+2
  3030                              <1> ;rootdir:.=.+2
  3031                              <1> ;toutt:	.=.+16.
  3032                              <1> ;touts: .=.+32.
  3033                              <1> ;runq:	.=.+6
  3034                              <1> ;
  3035                              <1> ;wlist:	.=.+40.
  3036                              <1> ;cc:	.=.+30.
  3037                              <1> ;cf:	.=.+31.
  3038                              <1> ;cl:	.=.+31.
  3039                              <1> ;clist:	.=.+510.
  3040                              <1> ;imod:	.=.+1
  3041                              <1> ;smod:	.=.+1
  3042                              <1> ;mmod:	.=.+1
  3043                              <1> ;uquant: .=.+1
  3044                              <1> ;sysflg: .=.+1
  3045                              <1> ;pptiflg:.=.+1
  3046                              <1> ;ttyoch: .=.+1
  3047                              <1> ; .even
  3048                              <1> ; .=.+100.; sstack:
  3049                              <1> ;buffer: .=.+[ntty*140.]
  3050                              <1> ;	.=.+[nbuf*520.]
  3051                              <1> ;
  3052                              <1> ; . = core-64.
  3053                              <1> ;user:
  3054                              <1> ;	u.sp:    .=.+2
  3055                              <1> ;	u.usp:   .=.+2
  3056                              <1> ;	u.r0:    .=.+2
  3057                              <1> ;	u.cdir:  .=.+2
  3058                              <1> ;	u.fp:    .=.+10.
  3059                              <1> ;	u.fofp:  .=.+2
  3060                              <1> ;	u.dirp:  .=.+2
  3061                              <1> ;	u.namep: .=.+2
  3062                              <1> ;	u.off:   .=.+2
  3063                              <1> ;	u.base:  .=.+2
  3064                              <1> ;	u.count: .=.+2
  3065                              <1> ;	u.nread: .=.+2
  3066                              <1> ;	u.break: .=.+2
  3067                              <1> ;	u.ttyp:  .=.+2
  3068                              <1> ;	u.dirbuf:.=.+10.
  3069                              <1> ;	u.pri:   .=.+2
  3070                              <1> ;	u.intr:  .=.+2
  3071                              <1> ;	u.quit:  .=.+2
  3072                              <1> ;	u.emt:   .=.+2
  3073                              <1> ;	u.ilgins:.=.+2
  3074                              <1> ;	u.cdev:  .=.+2
  3075                              <1> ;	u.uid:   .=.+1
  3076                              <1> ;	u.ruid:  .=.+1
  3077                              <1> ;	u.bsys:  .=.+1
  3078                              <1> ;	u.uno:   .=.+1
  3079                              <1> ;. = core
  2729                                  
  2730                                  bss_end:
  2731                                  
  2732                                  ; 27/02/2022
  2733                                  BSS_SIZE equ bss_end - bss_start
  2734                                  
  2735                                  ; 27/12/2013
  2736                                  _end:  ; end of kernel code (and read only data, just before bss)
